はなちるのマイノート

Unityをメインとした技術ブログ。自分らしくまったりやっていきたいと思いますー!

【Unity】コマンドラインからバッチモードでstaticメソッドを実行する方法

はじめに

今回はコマンドラインからUnityを操作する方法について紹介したいと思います。

コマンドラインから実行している様子

docs.unity3d.com

概要

Unityはコマンドラインから実行することができます。

Unity をコマンドラインで実行できます (macOS では ターミナル、Windows では コマンドプロンプト)。

コマンドライン引数 - Unity マニュアル

// Unityのスクリプト
namespace SampleNameSpace
{
    public class SampleClass
    {
        public static void SampleMethod()
        {
            Debug.Log("コマンドラインからこのメソッドが実行されました!");
        }
    }   
}
// MacのターミナルでSampleMethodを実行したサンプル
$ /Applications/Unity/Hub/Editor/2022.3.8f1/Unity.app/Contents/MacOS/Unity -quit -batchmode -nographics -projectPath "/Users/user/Sample2022_3_8f1" -executeMethod SampleNamespace.SampleClass.SampleMethod

Unity Editor version:    2022.3.8f1 (b5eafc012955)
Branch:                  2022.3/staging
Build type:              Release
Batch mode:              YES
macOS version:           Version 13.5.2 (Build 22G91)
Darwin version:          22.6.0
Architecture:            arm64
Running under Rosetta:   NO
Available memory:        32768 MB
...
コマンドラインからこのメソッドが実行されました!
...
Exiting batchmode successfully now!

利用するケースはCI/CDとかですかね。

コマンドについて

主要なもののみ紹介します。詳細は公式ドキュメントを参照してください。
docs.unity3d.com

とりあえずサンプルで紹介したコマンドが理解できるようになるところまでは最低限書きます。

$ /Applications/Unity/Hub/Editor/2022.3.8f1/Unity.app/Contents/MacOS/Unity -quit -batchmode -nographics -projectPath "/Users/user/Sample2022_3_8f1" -executeMethod SampleNamespace.SampleClass.SampleMethod

Unityのパスを指定

まずは最初にUnityのパスを指定する必要があります。

// Mac
$ /Applications/Unity/Unity.app/Contents/MacOS/Unity

// Windows
$ C:\Program Files\Unity\Editor\Unity.exe

コマンドライン引数 - Unity マニュアル

Macの場合はUnity.appの下にもContents/MacOS/Unityと続くことに注意してください。環境にもよるのだと思うのでFinderExploperなどを見ながら確認すると良いでしょう。

私の場合は以下のパスになっていました。

// Mac
$ /Applications/Unity/Hub/Editor/<バージョン>/Unity.app/Contents/MacOS/Unity
Finder上でのUnity.app

-quit

-quitは実行した後にUnityエディタが終了するようになります。ほとんどのケースで基本的につけて良いでしょう。また補足ではありますが、Unityエディタが起動している状態でコマンドを打ち込んでも正しく動作しないので注意してください。

コマンドの実行が終了した後に Unity エディターを終了します。これによりエラーメッセージが表示されなくなる場合があることに注意してください (ただし、エラーメッセージは Editor.log ファイルには保存されます)。

コマンドライン引数 - Unity マニュアル

-batchmode

UnityEditorが起動してもWindowが立ち上がらず、ユーザーがGUIから何か操作するみたいなことができなくなります。大体のケースでつけておいて大丈夫だと思います。

Unity をバッチモードで実行します。常に他のコマンドライン引数とともに使用してください。そうすることで、ポップアップウィンドウの表示を防ぎ、人間の介入を必要とさせないようにできます。スクリプトコードの実行中に例外が発生した場合、アセットサーバーの更新が失敗したり、他の操作が失敗した場合、Unity はただちにリターンコード 1 を送信して終了します。
バッチモードでは、Unity はログ出力の最小バージョンをコンソールに送信します。ただし、ログファイル には完全なログ情報が含まれます。エディターが同じプロジェクトを開いている間は、プロジェクトをバッチモードで開くことはできません。 Unityのインスタンスは1度に1つしか実行できません。
ヒント: バッチモードでエディターとスタンドアロンプレイヤーのどちらを実行しているかを確認するには、Application.isBatchMode 演算子を使用します。

  • batchmode を使用するときにプロジェクトがまだインポートされていない場合は、ターゲットプラットフォームはデフォルトのプラットフォームです。 -batchmode を使用するときに別のプラットフォームを強制的に使用するには、-buildTarget オプションを使用します。

コマンドライン引数 - Unity マニュアル

-nographics

グラフィックスデバイスの初期化を行わないようになります。コマンドラインからUnityを起動する場合は何かを描画したいケースはごく稀だと思うので、基本的に-nographicsはつけておいて良いと思います。

バッチモードを実行する時、グラフィックスデバイスの初期化をまったく行わないようにします。これによって、GPU のないマシンで自動化されたワークフローを実行出来るようになります (自動化されたワークフローは、ウィンドウにフォーカスがあるときのみ機能し、そうでない場合はシミュレーションされた入力コマンドは送信出来ません)。Enlighten には GPU アクセラレーション が必須なため、-nographics コマンドを使用した GI のベイクは行えません。

コマンドライン引数 - Unity マニュアル

-projectPath

プロジェクトのパスを指定します。これはつけましょう。

指定したパスのプロジェクトを開きます。

コマンドライン引数 - Unity マニュアル

-executeMethod

実行するstaticメソッドの場所を指定します。このときnamespaceもある場合は以下のように指定してあげます。

-executeMethod SampleNamespace.SampleClass.SampleMethod

またパラメーターの渡し方は後で紹介します。

Unity がプロジェクトを開いて、オプショナルなアセットサーバーの更新が完了した後に、この static メソッドを実行します。このコマンドは、継続的インテグレーション、ユニットテストの実施、ビルド作成、データ準備などのタスクを行うために使用します。コマンドライン処理のエラー結果が必要な場合は、例外を投げて Unity を戻り値 1 で終了させるか、ゼロ以外の戻り値を返すコード EditorApplication.Exit を呼び出します。パラメーターを渡したい場合は、コマンドラインにそれらを加えSystem.Environment.GetCommandLineArgs を使用して関数内で取得します。-executeMethod を使用する場合、加えるスクリプトを任意の Editor フォルダーに置かなければなりません。実行するメソッドは必ず static でなければなりません。

コマンドライン引数 - Unity マニュアル

-buildTarget

ビルドターゲットを選択できます。指定していない場合はデフォルトのプラットフォームになっています。

  • buildTarget プロジェクトをロードする前にアクティブなビルドターゲットを選択できます。可能なオプションは以下のとおりです。

Standalone、Win、Win64、OSXUniversal、Linux、Linux64、LinuxUniversal、iOS、Android、Web、WebStreamed、WebGL、XboxOne、PS4、WindowsStoreApps、Switch、N3DS、tvOS。

コマンドライン引数 - Unity マニュアル

-logFile

OSXではデフォルトでログはコンソールに出力されますが、-logFileをつけることでファイルとして出力することができます。

// サンプル
-logFile log.txt

エディターまたは Windows/Linux/OSX スタンドアロンのログファイルの保存場所を指定します。パスを指定しない場合は、OSX と Linux はコンソールに出力します。 Windows は %LOCALAPPDATA%\Unity\Editor\Editor.log をデフォルトのパスに使用します。

コマンドライン引数 - Unity マニュアル

引数の渡し方

-executeMethodを実行する際にパラメーターを渡したくなるケースもあると思います。

// サンプル
$ /Applications/Unity/Hub/Editor/2022.3.8f1/Unity.app/Contents/MacOS/Unity -quit -batchmode -nographics -projectPath "/Users/user/Sample2022_3_8f1" -executeMethod SampleNamespace.SampleClass.SampleMethod -hoge True -fuga hello,world!

パラメーターを渡したい場合はSystem.Environment.GetCommandLineArgsを使用して関数内で取得します。

namespace SampleNamespace
{
    public class SampleClass
    {
        public static void SampleMethod()
        {
            string[] args = System.Environment.GetCommandLineArgs();

            // コマンドラインの引数 : 12個
            Debug.Log($"️コマンドラインの引数 : {args.Length}個");
            foreach (var s in args)
            {
                // /Applications/Unity/Hub/Editor/2022.3.8f1/Unity.app/Contents/MacOS/Unity
                // -quit
                // -batchmode
                // -nographics
                // -projectPath
                // /Users/user/Sample2022_3_8f1
                // -executeMethod
                // SampleNamespace.SampleClass.SampleMethod
                // -hoge
                // True
                // -fuga
                // hello, world!
                Debug.Log($"引数 : {s}");
            }
        }
    }   
}

System.Environment.GetCommandLineArgsを実行するとコマンドラインの引数が全部取得できます。このとき-batchmodeなどのコマンドも取得してしまうことに注意してください。

解析するときはSystem.CommandLineを使ったりすると良いでしょう。
learn.microsoft.com