Unityのビルドでいろいろしてみた

# はじめに
今回はUnityのビルド時にいくつかやりたいことがあったため、試してみたいと思います。

# 使用したバージョン
Unity 2018.2.8f1

# バッチビルド
自動化の第一歩としてビルドを自動化する際によく使われているものになります。
Unityのバッチモードから事前に実装しておいたビルドを行う処理を呼び出す方法です。

まずはバッチモードで呼び出す処理の実装を行います。
サンプルでは、Androidへのビルドを想定して作成しています。

```cs:ApplicationBuild.cs
using System.Linq;
using UnityEditor;

public static class ApplicationBuild
{
    public static void AndroidBuild()
    {
        var levels = EditorBuildSettings.scenes
            .Where(scene => scene.enabled)
            .Select(scene => scene.path)
            .ToArray();
        BuildPipeline.BuildPlayer(levels, "./application.apk", BuildTarget.Android, BuildOptions.None);
    }
}
```

上記のスクリプトは、Build Settingsに設定されているシーンの中でEnableになっているシーンでビルドするスクリプトになっています。

次にバッチモードでコマンドラインから以下のコマンドを実行し、処理を呼び出してみます。

```bash:BuildBatch.bat
"Unity.exeへのパス" -batchmode -quit -projectPath "Unityプロジェクトへのパス" -executeMethod ApplicationBuild.AndroidBuild
```

無事にビルドが完了するとUnityプロジェクト直下にapplication.apkが生成されていると思います。

# デベロップメントビルド
ビルドを行う際にデバッグ版とリリース版を簡単に切り替えられるととても便利です。
デバッグ版とリリース版の切り替え自体は、UnityのDevelopment Buildフラグを利用して切り替えます。

先程利用したコマンドに`-development`という引数がついている場合はデバッグ版、ついていない場合はリリース版としてビルドを行うようにしたいと思います。

スクリプトを以下のように変更します。

```cs:ApplicationBuild.cs
using System.Linq;
using UnityEditor;

public static class ApplicationBuild
{
    private static BuildOptions _buildOptions = BuildOptions.None;

    public static void AndroidBuild()
    {
        var levels = EditorBuildSettings.scenes
            .Where(scene => scene.enabled)
            .Select(scene => scene.path)
            .ToArray();
        ResolveCommandLineArgs();
        BuildPipeline.BuildPlayer(levels, "./application.apk", BuildTarget.Android, _buildOptions);
    }

    private static void ResolveCommandLineArgs()
    {
        foreach (var command in System.Environment.GetCommandLineArgs())
        {
            switch (command)
            {
                case "-development":
                    _buildOptions = BuildOptions.Development;
                    break;
            }
        }
    }
}
```

いくつかのコマンドの中に`-development`が含まれている場合は、ビルドオプションをつけるようにしています。

先程のコマンドに`-development`を追加するとデバッグ版としてビルドができます。

```bash:BuildBatch.bat
"Unity.exeへのパス" -batchmode -quit -projectPath "Unityプロジェクトへのパス" -executeMethod ApplicationBuild.AndroidBuild -development
```

# ビルドに含めるシーンを切り替える
デバッグ版の場合にデバッグ用の機能へのアクセスやデバッグ表示などを行うシーンをビルドに含める処理を追加したいと思います。

```cs:ApplicationBuild.cs
using System.Collections.Generic;
using System.Linq;
using UnityEditor;

public static class ApplicationBuild
{
    private static List<string> _levels;
    private static BuildOptions _buildOptions = BuildOptions.None;

    private static string[] _debugScenes = new[]
    {
        "Assets/Scenes/Debug/DebugScene.unity",
    };

    public static void AndroidBuild()
    {
        _levels = EditorBuildSettings.scenes
            .Where(scene => scene.enabled)
            .Select(scene => scene.path)
            .ToList();
        ResolveCommandLineArgs();
        BuildPipeline.BuildPlayer(_levels.ToArray(), "./application.apk", BuildTarget.Android, _buildOptions);
    }

    private static void ResolveCommandLineArgs()
    {
        foreach (var command in System.Environment.GetCommandLineArgs())
        {
            switch (command)
            {
                case "-development":
                    _buildOptions = BuildOptions.Development;
                    _levels.AddRange(_debugScenes);
                    break;
            }
        }
    }
}
```

以前との差分は、下記の2点になります。

* デバッグ用のシーンへのパスをリストで保持するように変更
* `-development`が指定されている場合は、定義しておいたデバッグ用のシーン一覧を追加するように変更

デバッグ用のシーン一覧は、今回配列で指定するようにしていますが、`Directory.GetFiles`などを利用して`Assets/Scenes/Debug`以下のシーンを全て追加するようにするとわざわざ配列を追加する必要がなくなるた、便利になると思います。

# まとめ
* Unityのバッチモードからビルドを行う処理を呼び出せるようになりました。
* バッチモードでビルドした際に独自のコマンド引数を追加できるようになりました。
* デバッグ版とリリース版を切り替えられるようになりました。
* デバッグ用のシーンをデバッグ版のみに含めることが簡単になりました。

今回はコマンドラインからビルドを実行する方法とこんなことが簡単に設定できると良いなと思った部分について書きました。
バッチ部分をJenkinsから呼び出せるようにするとビルドの自動化ができます。
iOS側もXCodeプロジェクトのExportが同じようなスクリプトでできるようになります。

# 参考
[Unity - Manual: Command line arguments](https://docs.unity3d.com/Manual/CommandLineArguments.html)
[Unityエディタをバッチで起動し、プロジェクトにコマンドライン引数を渡す - Unityな日々（Unity Geek）](http://unitygeek.hatenablog.com/entry/2017/01/17/184427)