PONOS Advent Calendar 2024の21日目の記事です。
昨日は@FW14Bさんの「業務用ゲーム機の修理から学んだこと」でした。
はじめに
最近、コマンドラインからゲーム本編中のシーンをシミュレーションする仕組みを構築しようとしました。
これまでバイナリビルドのシステムを開発したりはしていましたが、ゲーム本編の処理を実行する経験はなかったので、初歩的ではありますが個人的に学びを得られたポイントをまとめたいと思います。
コマンドからUnityエディタを立ち上げて特定メソッドを実行する
先述の通りバイナリビルドのシステムを開発した経験があったため、バッチモードでUnityを実行する方法は知っていましたが、Unityエディタを立ち上げる方法を経験したことがなかったので、改めてコマンドでUnityを起動する方法を調べながら実装しました。
公式のドキュメントは「Unity エディターのコマンドライン引数 - Unity マニュアル」にあります。
結論、バッチモードで実行する場合との差は-batchmode
を省くだけであり、Unityエディタを起動して目的のメソッドを実行することができました。-executeMethod
はUnityエディタを起動した直後に実行する静的メソッドの名前を指定しています。
"** 使用しているUnityのパス(/Unity.app/Contents/MacOS/Unity) **" \
-projectPath "** Unityプロジェクトのルートディレクトリのパス **" \
-executeMethod GameSimulator.Simulate
sh start_simulation.sh
Unityエディタのプレイモードを開始する / 終了する
シーンの挙動をシミュレーションしたい場合、Unityエディタでプレイモードを開始する必要があります。
また、目的のシミュレーションが終了したときにはプレイモードを終了する必要もあります。
これらのプレイモードの状態の切り替えには、EditorApplication.isPlaying
の値を使用します。公式のドキュメントは「EditorApplication-isPlaying - Unity スクリプトリファレンス
」にあります。
使い方は簡単で、プレイモードを開始したいときにはtrue
を、終了したいときにはfalse
を設定するだけです。
// シミュレーションを開始するために、プレイモードを開始する。
EditorApplication.isPlaying = true;
// シミュレーションを終了するために、プレイモードを終了する。
EditorApplication.isPlaying = false;
シミュレーション中の情報を保持する
シミュレーションの進行中の情報を保存したい場合、Unityエディタの起動時に使用したstatic
なメソッドやクラスに保持させたいと考えますが、前述のプレイモードの開始をしていると容易にstatic
フィールドが初期化されてしまうため、情報を保持することができません。
シリアライズされた値は初期化されることがないため、EditorWindow
を用意して情報をシリアライズ可能にしておくことで保持することも可能ですが、基本的にシミュレーション中は人が操作・監視しないことを想定しているため、人の目に触れないウィンドウを作成するのは少し抵抗があります。
そこで今回自分はEditorPrefs
を利用して情報を保持する方法を採用しました。
EditorPrefs
に保存されていればプレイモードの切り替えでも情報が初期化される事はありませんし、シミュレーションの仕組みはエディタ拡張寄りの実装ですから、情報の置き場としても自然に感じます。
EditorPrefs
については「EditorPrefs - Unity スクリプトリファレンス」にあります。
// シミュレーションする回数を保存しておく。
EditorPrefs.SetInt("SimulationCountKey", simulationCount);
// シミュレーションを完了した回数を保存しておく。
EditorPrefs.SetInt("FinishCountKey", finishCount);
// シミュレーション回数が不足していたら次のシミュレーションを開始する。
var simulationCount = EditorPrefs.GetInt("SimulationCountKey");
var finishCount = EditorPrefs.GetInt("FinishCountKey");
if (finishCount < simulationCount)
{
// 次のシミュレーションの処理。
}
シミュレーション時に保持するべき情報が多い場合、個別に保存していると管理コストが高くついてしまうので、シリアライズ可能なデータクラスを定義し、それをJSON形式にシリアライズして一度に保存してしまうのがおすすめです。
Unityエディタ上でのシミュレーションを終了する
コマンドラインでの実行時に-quit
を指定していない場合、シミュレーションを終了するタイミングで明示的にUnityエディタを終了させる必要があります。
Unityエディタの終了にはEditorApplication.Exit
を実行します。ドキュメントは「Unity - Scripting API: EditorApplication.Exit」です。
EditorApplication.Exit(0);
なお、シミュレーションの結果についてはこのメソッドで返すことは難しいため、別途テキストで書き出すのが良いと思います。
まとめ
以上、簡単ではありますが、シミュレーションの機能を開発するうえで学んだポイントをまとめました。
ここで紹介した機能を利用することでシミュレーションの外枠については迷わず実行することができるようになると思います。
明日は@michel_mayonakaさんです!