コガネブログ

平日更新を目標に Unity や C#、Visual Studio、ReSharper などのゲーム開発アレコレを書いていきます

【Unity】IL2CPP ビルドした環境で Odin のシリアライズ周りでエラーが発生する場合の対応方法

はじめに

例えば上記のように JobType という列挙型が存在し、
その列挙型を Dictionary で使用している CharacterData という
SerializedScriptableObject が存在する場合に Example.Awake で
Resources.Load を使用して CharacterData を読み込もうすると
IL2CPP ビルドした環境だと以下のようなエラーが発生します

Creating a serialization formatter for the type 'System.Collections.Generic.Dictionary<int, JobType>' failed due to missing AOT support. 
 Please use Odin's AOT generation feature to generate an AOT dll before building, and MAKE SURE that all of the following types were automatically added to the supported types list after a scan (if they were not, please REPORT AN ISSUE with the details of which exact types the scan is missing and ADD THEM MANUALLY): 
System.Collections.Generic.Dictionary<int, JobType> (name string: 'System.Collections.Generic.Dictionary`2[[System.Int32, mscorlib],[JobType, Assembly-CSharp]], mscorlib')
System.int (name string: 'System.Int32, mscorlib')
JobType (name string: 'JobType, Assembly-CSharp')
IF ALL THE TYPES ARE IN THE SUPPORT LIST AND YOU STILL GET THIS ERROR, PLEASE REPORT AN ISSUE.The exception contained the following message: 
Attempting to call method 'Sirenix.Serialization.DictionaryFormatter`2[[System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77
ExecutionEngineException: Attempting to call method 'Sirenix.Serialization.DictionaryFormatter`2[[System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[JobType, Assembly-CSharp, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null]]::.cctor' for which no ahead of time (AOT) code was generated.
  at System.Reflection.MonoCMethod.InternalInvoke (System.Object obj, System.Object[] parameters) [0x00000] in <00000000000000000000000000000000>:0 
  at System.Activator.CreateInstance (System.Type type, System.Boolean nonPublic) [0x00000] in <00000000000000000000000000000000>:0 
  at Sirenix.Serialization.FormatterLocator.GetFormatterInstance (System.Type type) [0x00000] in <00000000000000000000000000000000>:0 
  at Sirenix.Serialization.FormatterLocator.CreateFormatter (System.Type type, Sirenix.Serialization.ISerializationPolicy policy) [0x00000] in <00000000000000000000000000000000>:0 
  at Sirenix.Serialization.FormatterLocator.GetFormatter (System.Type type, Sirenix.Seriali

これは、Odin の SerializedScriptableObject などで使用している型が
Unity の Code Stripping で削除されてしまうことで
型が見つからなくなってしまい、発生するエラーになります

今回の例では int 型や JobType 列挙型が Code Stripping されてしまい、
CharacterData のSerializedScriptableObject を読み込もうとした時に
型が見つからずデシリアライズに失敗してエラーになっています

この現象を避けるためには Odin の設定画面で
Code Stripping されてほしくない型の情報を設定します

手順

Unity メニューの「Tools > Odin Inspector > Preferences」を選択して

f:id:baba_s:20201123121123p:plain

Preferences ウィンドウが開いたら「AOT Generation」を選択して

f:id:baba_s:20201123121126p:plain

以下の項目をオンにします

  • Automate Before Builds
  • Delete Dll After Builds
  • Automate For All AOT Platforms

f:id:baba_s:20201123121129p:plain

そして、「Scan Project」ボタンを押します
Unity プロジェクトの規模によっては「Scan Project」の処理に時間がかかるので
しばらく待ちます

f:id:baba_s:20201123121132p:plain

処理が完了したら「Support Serialized Types」に型情報が追加されていることを確認します

これで Unity プロジェクトを IL2CPP ビルドして動作確認すると
エラーが発生しなくなります

もしも、これでもまだエラーが発生する場合は

f:id:baba_s:20201123121806p:plain

「Support Serialized Types」の「+」を押して

f:id:baba_s:20201123121827g:plain

IL2CPP ビルドした環境で見つからない型情報を手動で入力して追加します

f:id:baba_s:20201123121955p:plain

「INVALID」と表示される場合は入力した型情報の名前や名前空間の指定、
所属するアセンブリ名の指定が間違っていないか確認します

f:id:baba_s:20201123122000p:plain

「MODIFIED」と表示されていれば正常に入力できています