IL2CPPの事前コンパイル(AOT: Ahead-of-time)環境でジェネリッククラスやジェネリックメソッドをReflection(MakeGenericType/MakeGenericMethod)経由で使おうとするとExecutionEngineExceptionという例外が発生する場合がある。
事前コンパイルについてのUnityマニュアルはこちら: https://docs.unity3d.com/ja/current/Manual/ScriptingRestrictions.html
例えば以下のようなコードがあったとする。
// どこぞのメソッド内 var type = typeof(List<>).MakeGenericType(typeof(TestStruct)); // 他のコード上ではList<TestStruct>を直接使ってない。 var instance = System.Activator.CreateInstance(type); type.InvokeMember("Add", BindingFlags.Instance | BindingFlags.Public | BindingFlags.InvokeMethod, null, instance, new object[] { new TestStruct() }); // ここでExecutionEngineException Debug.Log(((IList<TestStruct>)instance)[0].ToString());
※InspectorウィンドウでTestStruct型を指定して、コード上ではそれが何なのか意識したくない場合に使うような想定
で、なぜこれで例外が発生するかというと
- IL2CPPはその名の通り、IL(.NET用の中間コード)をC++へ変換する。
- List<なんちゃら>をReflectionからのみ使用すると、事前にC++へ変換するときに「存在しないもの」なので未実装になる。
- 実行時にReflection経由で呼び出そうとすると「未実装なので実行できないよ」っと例外発生。
という感じ。
なので、以下のようにコンパイラーに存在を認識させれば動作するようになる。
// どこぞの型の中 public List<TestStruct> imhere = new List<TestStruct>();
この変数はコンパイラーが存在を認識して中身を実装さえしてくれれば良いので、宣言するだけしておけばOK
Unityのアセット販売中!
ステートマシンの状態遷移やパラメータはエディタで編集でき、
ゲームロジックに依存するステートの挙動はスクリプトで記述可能なエディタ拡張。
RPGツクールVXやWOLF RPGエディターのオートタイルに準拠したエディタ拡張。