LotosLabo

プログラミング技術とか気になった情報を載せていきます

Unityによる外部プロセスとの連携

利用方法

Unity上で外部プロセスを起動して、アウトプットを出力する例です。
外部プロセスを起動させて操作をし、その出力も欲しいという時に使います。

プロセス作成側


void ProcessStart()
{
    // プロセス作成.
    System.Diagnostics.Process process = new System.Diagnostics.Process();

    // 起動するプロセス.
    process.StartInfo.FileName = "C:\notepad.exe";
    
    // プロセス起動にシェルを使用するかどうか(defaultはfalse).
    process.StartInfo.UseShellExecute = false;

    // 標準出力を読み取り可.
    process.StartInfo.RedirectStandardOutput = true;

    // 標準出力イベント設定.
    process.OutputDataReceived += new System.Diagnostics.DataReceivedEventHandler(OutputHandler);

    // エラー出力読み取り可.
    process.StartInfo.RedirectStandardError = true;

    // エラー出力イベント設定.
    process.ErrorDataReceived += new System.Diagnostics.DataReceivedEventHandler(ErrorOutputHanlder);

  // 入力を読み取り不可.
    process.StartInfo.RedirectStandardInput = false;

  // 新しいウインドウを作成しない.
    process.StartInfo.CreateNoWindow = true;

    // 引数の指定(開くファイルの指定等).
    process.StartInfo.Arguments = "test.txt";

    // プロセス終了時にExitedイベントを発生.
    process.EnableRaisingEvents = true;

    // プロセス終了時に呼び出されるイベントの設定.
    process.Exited += new System.EventHandler(Process_Exit);

    // プロセスの起動.
    process.Start();

    // プロセス標準出力.
    process.BeginOutputReadLine();

  // プロセスエラー出力.
    process.BeginErrorReadLine();
}


全体の流れ

①プロセスの作成

②起動するプロセスの指定
C:\test.exeのように指定する場合と、
環境変数に登録してあるものが指定できる。(例:adb, svn

③オプションの指定

④イベントの設定

⑤プロセスの起動


※プロセスからの出力をイベント設定せずに出力してしまうと、途中で処理がフリーズしてしまうので、
出力がほしい時はこのように書きます。



プロセスの結果出力側


    // 標準出力時.
    private void OutputHandler(object sender, System.Diagnostics.DataReceivedEventArgs args)
    {
        if (!string.IsNullOrEmpty(args.Data))
        {
            Debug.Log(args.Data);
        }
    }
    
    // エラー出力時.
    private void ErrorOutputHanlder(object sender, System.Diagnostics.DataReceivedEventArgs args)
    {
        if (!string.IsNullOrEmpty(args.Data))
        {
            Debug.Log(args.Data);
        }
    }

    // プロセス終了時.
    private void Process_Exit(object sender, System.EventArgs e)
    {
            System.Diagnostics.Process proc = (System.Diagnostics.Process)sender;

            // プロセスを閉じる.
            proc.Kill();
    }
    


プロセスの使用例(adbを例として)

実際にUnityに拡張として作った「adb」を例に紹介していきます。
adbとはAndroid Debug Bridgeの略で、Androidデバッグをサポートするツールです。

通常使用する場合は、adbを環境変数として登録してcmdでadbコマンドを使用するか、
adb.exeが存在するカレントディレクトリ内でcmdでadbコマンドを実行するかです。

今回はこの動作をC#で、Unityで行っていく例を紹介します。

void ProcessStart()
{
    // 起動するプロセス.
    process.StartInfo.FileName = "C:\android-sdk-windows\platform-tools\adb.exe";

    // 引数の指定(コマンドの指定).
    process.StartInfo.Arguments = "version";

    /****************************
     *
     *          途中省略
     *         
     *****************************/

    // プロセスの起動.
    process.Start();
}


<起動するプロセス>

起動するプロセスに関しては、直接指定するか、環境変数にadbコマンドを指定している場合は、
"adb"のみの指定で起動できます。
エディター拡張として使用するなら、ファイルエクスプローラ開いて直接adbを選択してもらうほうがいいかもです。


<引数の指定>

ここでは adb [コマンド] のコマンドの部分を指定します。
例として、
version(バージョンの確認)
devices(接続しているデバイスの確認)
install [apkファイル名](apkのインストール)
kill-server(adbの停止)
start-server(adbの起動)


【cmdによる出力】

f:id:lo25131:20150927132630j:plain


【Unityによる出力】

f:id:lo25131:20150927132634j:plain



まとめ

Unityで外部プロセスを使用するにあたって、Visual Studioで開発する場合と記述の仕方は特に変わらないかと思います。
ただプロセスを使用するにあたって、起動したあと、エラーがあっても停止させることが重要です。
停止させないでいると、同じプロセスがタスクにたまってたまって、途中でフリーズする原因となってしまいます。

Unityから外部プロセスを起動するなどあまりないかもしれませんが、Editor拡張するときなどに使用するかもしれないので、
是非参考にしていただければと思います。