- Home /
IL2CPP Dictionary deserialization issue
Hi,
I build my project with scripting backend as IL2CPP(Unity 4.6.3 and Xcode 6.1.1). On building the project it is unable to deserialise the dictionary.
The error is : SerializationException: Could not find type 'System.Collections.Generic.Dictionary`2[[System.Int32, mscorlib, Version=2.0.5.0, '. at System.Runtime.Remoting.Messaging.RemotingSurrogate.GetObjectData (System.Object obj, System.Runtime.Serialization.SerializationInfo si, StreamingContext sc) [0x00000] in :0 at System.Runtime.Serialization.Formatters.Binary.ObjectReader.ReadType (System.IO.BinaryReader reader, TypeTag code) [0x00000] in :0 at System.Runtime.Serialization.Formatters.Binary.ObjectReader.ReadTypeMetadata (System.IO.BinaryReader reader, Boolean isRuntimeObject, Boolean hasTypeInfo) [0x00000] in :0 at System.Runtime.Serialization.Formatters.Binary.ObjectReader.ReadObjectInstance (System.IO.BinaryReader reader, Boolean isRuntimeObject, Boolean hasTypeInfo, Int64& objectId, System.Object& value, System.Runtime.Serialization.SerializationInfo& info) [0x00000] in :0 at System.Runtime.Serialization.Formatters.Binary.ObjectReader.ReadObject (BinaryElement element, System.IO.BinaryReader reader, Int64& objectId, System.Object& value, System.Runtime.Serialization.SerializationInfo& info) [0x00000] in :0 at System.Runtime.Serialization.Formatters.Binary.ObjectReader.ReadNextObject (System.IO.BinaryReader reader) [0x00000] in :0 at System.Runtime.Serialization.Formatters.Binary.ObjectReader.ReadObjectGraph (BinaryElement elem, System.IO.BinaryReader reader, Boolean readHeaders, System.Object& result, System.Runtime.Remoting.Messaging.Header[]& headers) [0x00000] in :0 at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.NoCheckDeserialize (System.IO.Stream serializationStream, System.Runtime.Remoting.Messaging.HeaderHandler handler) [0x00000] in :0 at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize (System.IO.Stream serializationStream) [0x00000] in :0 at AutoSpriteControlBase.IUIObject.get_name () [0x00000] in :0 at EncodeData.Decode[FeedAnimalsTime] () [0x00000] in :0 at GameState.get_ActualGameState () [0x00000] in :0 at SplashSceneScript+c__Iterator10.MoveNext () [0x00000] in :0 at Replacements.MSCompatUnicodeTable.get_IsReady () [0x00000] in :0 at UnityEngine.MonoBehaviour.StartCoroutine_Auto (IEnumerator routine) [0x00000] in :0 at UnityEngine.MonoBehaviour.StartCoroutine (IEnumerator routine) [0x00000] in :0 at SplashSceneScript.LoadNextScene () [0x00000] in :0 at Replacements.MSCompatUnicodeTable.get_IsReady () [0x00000] in :0 Replacements.MSCompatUnicodeTable:get_IsReady() UnityEngine.MonoBehaviour:StartCoroutine_Auto(IEnumerator) UnityEngine.MonoBehaviour:StartCoroutine(IEnumerator) SplashSceneScript:LoadNextScene() Replacements.MSCompatUnicodeTable:get_IsReady()
(Filename: currently not available on il2cpp Line: -1)
There is no such issue when building the project with Mono(2.x) as scripting backend. I request you to please look into the issue as my game is completed and it is working fine for 32-bit support
Answer by JoshPeterson · Mar 31, 2015 at 11:32 AM
It looks like this problem occurs because a generic dictionary type cannot be constructed at run time by the serializer. You can give IL2CPP some hints about what generic types will be needed a runtime, and likely avoid this problem, but following the process described in this forum post:
http://forum.unity3d.com/threads/il2cpp-type-makegenerictype-work-around.311926/
Note that you will need at least version 4.6.3p4 to make this work.
@Josh , can you please elaborate how to describe a dictionary in AssemblyQualifiedName . It's something like :
System.Collections.Generic.Dictionary`2[ Custom Enum type , Custom Class ]
We're trying to figure out how to mention these Custom Enum and Class as Type of Dictionary in il2cpp_extra_types.txt .
cheers
@arun.pandey89 It looks like you are on the right track. You should be able to replace "Custom Enum type" and "Custom Class" in this example with the namespace and type name of each, just like you have done with the Dictionary type. If this does not work, please let me know the string you are trying to use. Thanks.
Answer by arun.pandey89 · Apr 06, 2015 at 04:23 PM
@Josh we have tried these entries in text file and it didn't work out. Can you see any problem with namespaces or their types ? do you have any alternative solution ?
System.Collections.Generic.Dictionary`2[System.Enum , UnityEngine.Object] **on behalf of Dictionary<Enum value , MonoBehaviour>**
System.Collections.Generic.Dictionary`2[System.Int32, System.Collections.Generic.List<T>] **on behalf of Dictionary<int value , list <int>>**
System.Collections.Generic.Dictionary`2[System.Enum, System.Single] **on behalf of Dictionary<Enum value , Float value>**
System.Collections.Generic.Dictionary`2[System.Enum, System.Object] **on behalf of Dictionary<Enum value , Scriptable Class>**
I think that in all cases, il2cpp_extra_types.txt needs to have the most-derived classes mentioned explicitly. So base types like System.Enum and UnityEngine.Object won't work.
In general, il2cpp_extra_types.txt is only useful if you cannot include the generic type you would like to tell the AOT compiler in your C# code directly (e.g. the type is internal to an assembly for which you don't have the source code).
A better alternative is to create a public static field in a class derived from $$anonymous$$onoBehavior for each of the type you need to tell the AOT compiler about.
This alternative still won't work with base types, but at least the syntax is more familiar, since it is normal C# code.
@Josh , logically speaking it should have worked . As it is supposed to work for System.String or System.Int . Any other way to mention those derived type in text file . $$anonymous$$oreover creating static dictionary is not gonna work as we need to serialiize those dictionaries .
@arun.pandey89 Unfortunately, there is no way to make this work with base class types, you do need to mention all of the derived types.
For the static dictionary. The intention is not to actually use the static dictionary at runtime, it does not have to be involved in the serialization at all. However we do need to know the type which will be used in the serialization, and use that type in a static field. As long as the type exists, IL2CPP will generate the proper code for that type, and the serialization code will find that type at runtime.
Note that if things will not work, it might be worth submitting a bug so that we can have a look, as we may have missed some case as well.
Answer by Voxel-Busters · Jun 08, 2015 at 07:31 AM
Recently we released Runtime Serialization for Unity plugin which handles all the above mentioned issues, like
Serializing dictionary object of type
Serializing base class instance and while deserialising you will fetch the original derived class object.
Now you may ask, how's that possible ???
Actually when we serialise an object of any given type, we serialize its metadata along with the value. So this extra metadata serialization done by our plugin makes it possible to retrieve the original object after deserializing.