名古屋スタジオでクライアントエンジニアをしている長屋と申します。
とあるUnityプロジェクトで演出制御のためにBoltを利用していますが、
実機でのみ発生するエラーに遭遇したのでその際のことを書こうと思います。
エラー発生時の環境
・ macOS Catalina
・ Unity 2019.4.3f1
・ Bolt 1.4.13
事の発端
Bolt上で演出制御を組み込み、いざiOS実機上でアプリを実行すると、演出が発生せずXcode上のエラーログ内で「ahead-of-time(AOT)」の例外が大量に吐かれていました。。。。
Androidでも実機確認をした結果、こちらもエラーで演出が発生しませんでした。。。。
エラー内容
Failed to define GetMember#e0e3c...:
System.NotSupportedException: IL2CPP encountered a managed type which it cannot convert ahead-of-time. The type uses generic or array types which are nested beyond the maximum depth which can be converted.
at System.RuntimeType.GetGenericParameterAttributes () [0x00000] in :0
at Ludiq.TypeUtility.CanMakeGenericTypeVia (System.Type openConstructedType, System.Type closedConstructedType) [0x00000] in :0
at Ludiq.MemberUtility+d__8.MoveNext () [0x00000] in :0
~~~ 以下似たようなエラーコード ~~~
Unityのシミュレーター上では発生しないとても厄介なエラーです。
エラー解消の為以下の方法を試しました。
①「Tools > Bold > AOT Pre-Build」
を再度実行
Boltが関わるAOTエラーでよく原因に上がるのがAotStubs.cs
ファイルの更新漏れです。
Boltで作成したものをiOS及びAndroidの実機上で実行する際は、一度「AOT Pre-Build」を実行してAotStubs.cs
ファイルを作成及び更新する必要があります。
当然こちらは試しましたが、エラーは解決せず。。。。。。。
②「IL2CPP」のコンパイル時に追加引数を渡す
ここで一度エラーコードを読み解いてみると
IL2CPP encountered a managed type which it cannot convert ahead-of-time.
The type uses generic or array types which are nested beyond the maximum depth which can be converted.
と表示されています。
恐らくジェネリクスの型展開のネスト深度の上限を超えてしまったのでは?
とあたりをつけ関連情報を対応チームで調査した結果Unity 2019.4.15f1からネスト深度の上限を増やせるオプションが追加されていることがわかりました。
Unity Relese Node
https://unity3d.com/jp/unity/whats-new/2019.4.15
IL2CPP: Fixed to enforce the --maximum-recursive-generic-depth command line option at run time. (1276405)
今回はUnityを2019.4.16f1へアップデート後、
「UnityEditor.PlayerSettings」 クラス経由で IL2CPP.exe
に対して上記のオプションを追加してあげることでiOSとAndroid共にエラーを回避できました。
// 値を増やしすぎるとコンパイル時間が増大するそうです。
UnityEditor.PlayerSettings.SetAdditionalIl2CppArgs("--maximum-recursive-generic-depth=20");
最後に
今回の方法ではあくまでネスト上限を引き上げているだけなので根本解決にはなりません。
ユーザーソースの参照量次第では再度上限を超える可能性もあります。
根本解決をする場合は「Tool > Bolt > SetupWizard」からBoltが参照するAssembly Definitionを制限して参照されるコード自体を減らしてあげると良いと思います。