はなちるのマイノート

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

【Unity, C#】System.Environment.GetCommandLineArgsとSystem.CommandLineを用いてコマンドライン引数にて配列を受け取る方法

はじめに

今回はUnityのコマンドライン引数にて配列を受け取る方法を紹介したいと思います。

// 「-- hoge aaa --hoge bbb --hoge ccc」もしくは「--hoge aaa bbb ccc」のようにコマンドライン引数を受け取れる
$ /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 aaa --hoge bbb --hoge ccc

またSystem.CommandLineの説明だけでUnity関係ないやんと思うかもしれませんが、UnityではSystem.Environment.GetCommandLineArgsで引数を受け取る都合上、少し気をつけないといけない箇所があったのでこのようにしているのであしからず。

インストール方法

書かなくても良いかもしれませんが、System.CommandLineパッケージのインストール方法も書いておきます。

ダウンロードする手法は色々ありますが、シンプルなものはnuget.orgからとってくる手法でしょう。

  1. nuget.orgDownload packagesボタンを押してnupkgをダウンロード
  2. 拡張子を.zipに書き換えて展開
  3. フォルダの中のlib/netstandard2.0の中にあるSystem.CommandLine.dllをUnityのAssets/Pluginsフォルダの中に入れる

www.nuget.org

System.CommandLine.dllをPluginsの中に入れる

配列を受け取る

配列を受け取るためにはOption.AllowMultipleArgumentsPerTokenを利用します。

// サンプル
// 以下のように受け取ることができるオプション
// --hoge 1 2 3
// --hoge 1 --hoge 2 --hoge 3
Option option = new Option<IEnumerable<string>>("--hoge")
{
    // オプション識別子トークンごとに複数の引数トークンが許可する
    AllowMultipleArgumentsPerToken = true
};

learn.microsoft.com

一致しないトークンがエラーになる問題

Unityでコマンドライン引数を受け取る場合はSystem.Environment.GetCommandLineArgsを利用します。

パラメーターを渡したい場合は、コマンドラインにそれらを加えSystem.Environment.GetCommandLineArgsを使用して関数内で取得します。

docs.unity3d.com

このSystem.Environment.GetCommandLineArgsですがUnity固有のオプションも含まれるので、そのままSystem.CommandLineを利用しようとすると一致しないトークンがありエラーが出るみたいなことが多々あります。

// サンプル
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}");
            }
        }
    }   
}

そんなときは一致しないトークンをエラーと扱わないようにしてあげるCommand.TreatUnmatchedTokensAsErrorsを使ってあげると良いでしょう。

一致しないトークンをエラーとして扱う必要があるかどうかを示す値を取得または設定します。 たとえば、 を に true 設定し、追加のコマンドまたは引数を指定すると、検証は失敗します。

learn.microsoft.com

RootCommand rootCommand = new RootCommand();

// System.Environment.GetCommandLineArgsはUnity固有のTokenも入ってきてしまうので、一致しないトークンをエラーとして扱わないようにしておく
rootCommand.TreatUnmatchedTokensAsErrors = false;

実際のサンプル

これらを組み合わせて実際に動くサンプルを書いてみました。

string[] args = System.Environment.GetCommandLineArgs();

// 以下のように受け取ることができるオプション
// --hoge 1 2 3
// --hoge 1 --hoge 2 --hoge 3
Option<string[]> option = new Option<string[]>("--hoge")
{
    // オプション識別子トークンごとに複数の引数トークンが許可する
    AllowMultipleArgumentsPerToken = true
};

RootCommand rootCommand = new RootCommand();
rootCommand.AddOption(option);

// System.Environment.GetCommandLineArgsはUnity固有のTokenも入ってきてしまうので、一致しないトークンをエラーとして扱わないようにしておく
rootCommand.TreatUnmatchedTokensAsErrors = false;
            
ParseResult parseResult = rootCommand.Parse(args);

if (parseResult.Errors.Count != 0)
{
    foreach (var resultError in parseResult.Errors)
    {
        Debug.LogError(resultError);
    }
    EditorApplication.Exit(1);
}

var hoge = parseResult.GetValueForOption(option);

if (hoge != null)
{
    foreach (var s in hoge)
    {
        Debug.Log(s);
    }
}

EditorApplication.Exit(0);


実行の仕方については以下の記事を参考にしてほしいですが、例えば以下のコマンドを打つとちゃんと動作することが確認できます。
www.hanachiru-blog.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 --hoge aaa --hoge bbb --hoge ccc