Search Unity

iOS Basic BinaryFormatter

Discussion in 'iOS and tvOS' started by aBs0lut30, Jun 20, 2012.

  1. aBs0lut30

    aBs0lut30

    Joined:
    May 17, 2012
    Posts:
    3
    Hi Guys, I have got an issue. I have been working on a project on a unity Pro trial. This morning I went out and bought the iOS basic license and installed it into unity. Ran my project in the editor and everything was fine. So, I built it for the device, everything compiled fine, it installed ran and promptly crashed. Being that it's basic I cannot connect to debug the line where its breaking but the error that XCode gives is System.ExecutionEngineException Attempting to JIT compile method coinPattern__TypeMetadata:.ctor()

    Now, coin Pattern is a struct, but nothing unusual in it, some strings, bools and an array. Everything works fine under pro, and under basic it works in the editor just fine. Does anyone have any idea what the problem is or how to fix it? I have seen ton's of threads talking about it, but dont really see anything that applies to what I am getting...

    Please help...
     
  2. prime31

    prime31

    Joined:
    Oct 9, 2008
    Posts:
    6,426
    BinaryFormatter requires JIT compile which isn't available on mobile (AOT compiled). Either write your own or use something like Googles protocol buffers or the XML serializer.
     
  3. sims11tz

    sims11tz

    Joined:
    Nov 20, 2011
    Posts:
    15
    BinaryFormatter works in Unity 3.5.5f3 on ios... just got a prototype working on an ipad3

    Code (csharp):
    1.  
    2. //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
    3. //BinaryFormatter String Way
    4.     public static BinaryFormatter bf = new BinaryFormatter();
    5.     public static String serializeStr(object serializableObject)
    6.     {
    7.         MemoryStream memoryStream = new MemoryStream();
    8.         bf.Serialize(memoryStream, serializableObject);
    9.  
    10.         return System.Convert.ToBase64String(memoryStream.ToArray());
    11.     }
    12.  
    13.     public static object deserializeStr(string byteArray)
    14.     {
    15.         MemoryStream memoryStream = new MemoryStream(System.Convert.FromBase64String(byteArray));
    16.  
    17.         return bf.Deserialize(memoryStream);
    18.     }
    19.  
    20. //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
    21. //BinaryFormatter Byte Array way
    22.     public static byte[] SerializeToByteArray(object request)
    23.     {
    24.         byte[] result;
    25.         BinaryFormatter serializer = new BinaryFormatter();
    26.         using (MemoryStream memStream = new MemoryStream())
    27.         {
    28.             serializer.Serialize(memStream, request);
    29.             result = memStream.GetBuffer();
    30.         }
    31.         return result;
    32.     }
    33.  
    34.     public static object DeserializeFromByteArray(byte[] buffer)
    35.     {
    36.         BinaryFormatter deserializer = new BinaryFormatter();
    37.         using (MemoryStream memStream = new MemoryStream(buffer))
    38.         {
    39.             object newobj = deserializer.Deserialize(memStream);
    40.             return newobj;
    41.         }
    42.     }
    43.  
     
  4. J_P_

    J_P_

    Joined:
    Jan 9, 2010
    Posts:
    1,027
    Really? I Get: ExecutionEngineException: Attempting to JIT compile method 'MatchData__TypeMetadata:.ctor ()' while running with --aot-only.

    edit: Interesting. It works if I have stripping level set to micro mscorlib. Not sure if I'll want to keep relying on this or not though..
     
    Last edited: Sep 27, 2012
  5. sims11tz

    sims11tz

    Joined:
    Nov 20, 2011
    Posts:
    15
    Hey Prime, do you sale any plugins that will turn an object into a byte array on ios?

    Dang, so I had BinaryFormatter working with a simple prototype .... and now my project has grown and has more advanced datatypes and now I am getting an error.


    ExecutionEngineException: Attempting to JIT compile method 'GenericEqualityComparer`1__TypeMetadata:.ctor ()' while running with --aot-only.

    at System.Reflection.MonoCMethod.Invoke (System.Object obj, BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) [0x00000] in <filename unknown>:0
    Rethrow as TargetInvocationException: Exception has been thrown by the target of an invocation.
     
  6. prime31

    prime31

    Joined:
    Oct 9, 2008
    Posts:
    6,426
    @sims, I personally use Google Protocol Buffers for serializing/deserializing objects. It works like a charm though it does require a bit of additional setup (all serializeable objects must be in a separate DLL). You can always use JSON or an XML serializer as well which are quite easy to implement.
     
  7. sims11tz

    sims11tz

    Joined:
    Nov 20, 2011
    Posts:
    15
    word, I did investigate Google Protocol Buffers,..... we have a huge project that is due in December so it scared me to have all that additional setup. Do you have a particular tutorial that used or any good info on the net to get Protocol Buffers working? We essentially only have like 6 classes that we need serialized so maybe using protocol buffers isn't out of the question. The thing that got me excited was the performance that people listed with protocol buffers ... SO FAST and gets the data packed down REALLY SMALL!

    The article i read was http://www.frictionpointstudios.com...otobuf-net-serialization-in-unity-iphone.html was a great read but from 2011 which was a bit out dated.

    by the way I love your plugins i own a couple :)
     
  8. sims11tz

    sims11tz

    Joined:
    Nov 20, 2011
    Posts:
    15
    so I just tried the XML serializer really quick and it cant serialize a hashtable or generic dictionary which I am using both... do you know if Protocol Buffers can do these types?
     
  9. prime31

    prime31

    Joined:
    Oct 9, 2008
    Posts:
    6,426
    I haven't a clue. I never use Hashtables and only serialize model objects and Lists of model objects.
     
  10. sims11tz

    sims11tz

    Joined:
    Nov 20, 2011
    Posts:
    15
    Myself and another programmer just paired up and translated our vo system to protocol buffers. we switched our hash tables to generic dictionaries and it works amazing!!! you were right it was way simple to get going once you figure it out. I will post some sample code when i get home later tonight for anybody that stumbles onto this post. But Protocol Buffers is the way to go FOR sure on ios and Unity.
     
  11. sims11tz

    sims11tz

    Joined:
    Nov 20, 2011
    Posts:
    15
    At the time of writing this : Unity 3.5.6f4 10/5/2012 works on ios 6 and below

    Ok,..... so if you stumble onto this post and you want to serialize objects in Unity on an ios device this is the direction you should go for sure !!!

    Here is the tutorial that i followed to do this, it was a bit old and I had to change a couple things.
    Awesome Tutorial : Friction Point Studios - USING PROTOBUF-NET SERIALIZATION IN UNITY IPHONE

    --------------------------------------------------------------------------------------------------------------------------------------------------------------------

    Google Protocol Buffers-net = http://code.google.com/p/protobuf-net/


    Get Protobuff lib
    Download protbuf-net : protobuf-net r580.zip protobuf-net v2 r580 from http://code.google.com/p/protobuf-net/downloads/list

    unzip protobuf-net the .dll that you want is in UNZIPPED-FOLDER/protobuf-net r580/Full/unity/protbuf-net.dll


    You will need 2 Visual Studio Projects and your Unity Project, I have no clue how to do this without Visual Studio, but I would imagine there is a way.

    Project 1 - Data Model Project *i named my project BitchModels
    Create a new Visual Studio Project - Project Type Class Library
    In your Solution Explorer : Add a Reference to protobuf-net.dll
    Create a main class , in my case it is called BitchModels.cs

    *Note : You cannot serialize UnityEngine natives as you see in my example i provide a way to translate a Vector3.. you can use this same idea for Vector2, Quaternion and all sorts of Unity natives.

    Here is what my BitchModels.cs looks like

    Code (csharp):
    1.  
    2. using System;
    3. using System.Collections.Generic;
    4. using System.Text;
    5. using ProtoBuf;
    6.  
    7. namespace BitchModels
    8. {
    9.     [ProtoContract]
    10.     public class BitchState
    11.     {
    12.         [ProtoMember(1)]
    13.         public int id;
    14.         [ProtoMember(2)]
    15.         public bool isBitch;
    16.         [ProtoMember(3)]
    17.         public float energy;
    18.         [ProtoMember(4)]
    19.         public string name;
    20.         [ProtoMember(5)]
    21.         public TranslateVector3 position;
    22.         [ProtoMember(5)]
    23.         public TranslateQuaternion rotation;
    24.     }
    25.  
    26.     [ProtoContract]
    27.     public class BitchStateList
    28.     {
    29.         [ProtoMember(1)]
    30.         public Dictionary<int, BitchState> serializableItems;
    31.     }
    32. }
    33.  
    34. [ProtoContract]
    35.     public class TranslateVector3
    36.     {
    37.         [ProtoMember(1)]
    38.         public float x;
    39.         [ProtoMember(2)]
    40.         public float y;
    41.         [ProtoMember(3)]
    42.         public float z;
    43.  
    44.         public BVVector3()
    45.         {
    46.             this.x = 0.0f;
    47.             this.y = 0.0f;
    48.             this.z = 0.0f;
    49.         }
    50.  
    51.         public TranslateVector3(float x, float y, float z)
    52.         {
    53.             this.x = x;
    54.             this.y = y;
    55.             this.z = z;
    56.         }
    57.     }
    58.  
    59.  [ProtoContract]
    60.     public class TranslateQuaternion
    61.     {
    62.         [ProtoMember(1)]
    63.         public float x;
    64.         [ProtoMember(2)]
    65.         public float y;
    66.         [ProtoMember(3)]
    67.         public float z;
    68.         [ProtoMember(4)]
    69.         public float w;
    70.  
    71.         public TranslateQuaternion()
    72.         {
    73.             this.x = 0.0f;
    74.             this.y = 0.0f;
    75.             this.z = 0.0f;
    76.             this.w = 0.0f;
    77.         }
    78.  
    79.         public TranslateQuaternion(float x, float y, float z, float w)
    80.         {
    81.             this.x = x;
    82.             this.y = y;
    83.             this.z = z;
    84.             this.w = w;
    85.         }
    86.     }
    87.  
    Now in this project, run Build or press Control+Shift+B ... your solution will create a file called BitchModels.dll
    output is something like :
    ------ Build started: Project: BitchModels, Configuration: Release Any CPU ------
    BitchModels -> C:\BVModels\bin\Release\BitchModels.dll
    ========== Build: 1 succeeded or up-to-date, 0 failed, 0 skipped ==========



    Project 2 - Bitch Serialize Creator Project *i named my project BitchSerialCreator
    Create a new Visual Studio Project - Project Type Console Application
    In your Solution Explorer : Add a Reference to protobuf-net.dll AND also add a reference to your new BitchModels.dll
    Create a main class , in my case it is called program.cs

    Here is my BitchSerialCreator.cs

    Code (csharp):
    1.  
    2. using System;
    3. using System.Collections.Generic;
    4. using ProtoBuf;
    5. using ProtoBuf.Meta;
    6. using ProtoBuf.Compiler;
    7. using BitchModels;
    8.  
    9. namespace BitchSerialCreator
    10. {
    11.     class program
    12.     {
    13.         static void Main(string[] args)
    14.         {
    15.             var model = TypeModel.Create();
    16.             model.Add(typeof(object), true);
    17.             model.Add(typeof(BitchState), true);
    18.             model.Add(typeof(BitchStateList), true);
    19.             model.Add(typeof(TranslateVector3), true);
    20.             model.Add(typeof(TranslateQuaternion), true);
    21.  
    22.             model.AllowParseableTypes = true;
    23.             model.AutoAddMissingTypes = true;
    24.  
    25.             model.Compile("BitchSerializer", "BitchSerializer.dll");
    26.         }
    27.     }
    28. }
    29.  
    Build the solution and then hit Play in Visual Studio to run the program. This will output a bunch of files into your Solutions bin folder.
    copy the following files out of your bin folder :
    • BitchModels.dll
    • BitchSerializer.dll
    • protobuf-net.dll

    Place these .dlls into your unity project somewhere,... Unity will automaticall find them or in your unity project hit import and add them.




    Project 3 - Bitch Unity Project
    Now should be the easy part as you all know Unity and C#

    I create a game object and placed onto my scene and added a class called Bitch.cs to the game object.

    Here is what my Bitch.cs looks like:

    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using System.Collections;
    4. using System.Collections.Generic;
    5. using BitchModels;
    6.  
    7. public class BitchNuts: MonoBehaviour
    8. {
    9.     public override void Start()
    10.     {
    11.  
    12.         //Create 5 bitch states and add them to a bitch list
    13.         BitchStateList bitchList = new BitchStateList ();
    14.         bitchList .serializableItems = new Dictionary<int, BitchState>();
    15.         BitchState bitchState = new BitchState();
    16.  
    17.         for(int i = 0; i < 5; i++)
    18.         {
    19.             bitchState = new BitchState();
    20.             bitchState.isBitch= true;
    21.             bitchState.energy = 34.3f;
    22.             bitchState.name = "Bitch_"+i;
    23.             bitchState.position = new TranslateVector3(1f, 2f, 3f);
    24.             bitchState.rotation= new TranslateQuaternion(1f, 2f, 3f, 4f);
    25.             bitchList.serializableItems.Add(i, bitchState );
    26.         }
    27.  
    28.         //run the bitch list through the BitchSerializer
    29.         BitchSerializer mySerializer = new BitchSerializer();
    30.         MemoryStream memoryStream = new MemoryStream();
    31.         mySerializer.Serialize(memoryStream, bitchList);
    32.         string serializedStr = System.Convert.ToBase64String(memoryStream.ToArray());
    33.  
    34.         //HERE IS OUR AMAZING SERIALIZED OBJECTS, we could save to device or send to database!
    35.         Debug.Log("SERIALIZED OBJECT "+serializedStr .toString());
    36.            
    37.         //lets unserialize the data and read it out
    38.         MemoryStream stream = new MemoryStream(System.Convert.FromBase64String(serializedStr ));
    39.         BitchStateList readBitchList = new BitchStateList ();
    40.         mySerializer.Deserialize(stream, readBitchList , typeof(BitchStateList));
    41.            
    42.         foreach(KeyValuePair<int, BitchState> readBitchState in readBitchList.serializableItems)
    43.         {
    44.             Debug.Log(" "+readBitchState .Key);
    45.             Debug.Log("isBitch:"+readBitchState.Value.isBitch);
    46.             Debug.Log("energy :"+readBitchState.Value.energy );
    47.             Debug.Log("name :"+readBitchState.Value.name );
    48.             Debug.Log("position :"+readBitchState.Value.position);
    49.             Debug.Log("rotation:"+readBitchState.Value.rotation);
    50.             Debug.Log("");
    51.         }
    52.  
    53.     }
    54.  
    55. }
    56.  



    AMAZING RIGHT !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! :cool: Lemme know if this is not totally clear or I can help with any qeustions. You can do way more then what I showed you can also do inheritance in your serializer classes and all sorts of cool S***.

    i hope this helps some people I googled on this subject for days and didn't find much good data. Just remember Protocol Buffers is the way to go and way easier then it first appears to be.

    and thanks prime[31] !

    -dave
     
    Last edited: Oct 10, 2012
  12. Dosetsu

    Dosetsu

    Joined:
    Dec 22, 2011
    Posts:
    39
    I jumped through a whole bunch of hoops attempting other solutions. Just save yourself the trouble, and use the google protocol buffers. Its a bit of work, but nothing compared to failing with other solutions for days. Buckle down and power through.

    Two bits of advice here

    1. the DLL you want to reference is in your lib is protobuf-net r602/Full/unity/protobuf-net.dll
    2. use the precompile.exe to make your compiled dll thusly
    mono ../../../../protobuf-net\ r602/Precompile/precompile.exe MyAwesomeLib.dll -o:Serializer.dll -t:MySerializer

    In the end you'll have something that is AOT compiled and you'll be ready to use this technique in any other project from now on.
     
  13. basil

    basil

    Joined:
    Dec 13, 2012
    Posts:
    9

    --> I also got error message like yours,
    -->have you fixed it?
    --> what do you mean about "It works if I have stripping level set to micro mscorlib."? HOPE you can help me

    THANKS!!!
     
  14. whydoidoit

    whydoidoit

    Joined:
    Mar 12, 2012
    Posts:
    365
    I'd just like to point out that my free UnitySerializer library works on IOS and can turn any class into a byte array and back and also has a ton of handling for special Unity objects (sequences of setting vectors and transforms etc). Its performance is comparable to BinaryFormatter (hence a lot faster than XML).

    It also contains functionality for complete level saving and loading - room management, individual game object management, upload/download from servers etc.
     
  15. whydoidoit

    whydoidoit

    Joined:
    Mar 12, 2012
    Posts:
    365
    You should try fiddling with the Optimization settings for API compatibility level and Stripping Level in Player Settings/iPhone of your project.

    A number of JITs happen in random places in Unity based on the library level used.
     
  16. mechanodroid

    mechanodroid

    Joined:
    May 7, 2013
    Posts:
    1
    Changing it to "micro mscorlib" fixed it for me! Thanks!
     
  17. antonholmquist

    antonholmquist

    Joined:
    Apr 30, 2013
    Posts:
    1
    I fixed the JIT compile error just by adding this line:
    Code (csharp):
    1. Environment.SetEnvironmentVariable("MONO_REFLECTION_SERIALIZER", "yes")"
    I created a simple GitHub project which wraps the serialization process, compatible with iOS: https://github.com/antonholmquist/easy-serializer-unity

    Credits to this thread: http://answers.unity3d.com/questions/30930/why-did-my-binaryserialzer-stop-working.html

    By the way, changing to "micro mscorlib" is probably not a great idea in general since it could potentially break other stuff. From Unity's website: "This optimization reduces the main binary and mscorlib.dll size but it is not compatible with some System and System.Xml assembly classes, so use it with care."
     
    Last edited: Dec 3, 2013
    Ali_V_Quest likes this.
  18. Petro19

    Petro19

    Joined:
    Jan 17, 2013
    Posts:
    3
    thanks, it works!
     
  19. DNA-Studios

    DNA-Studios

    Joined:
    Oct 22, 2012
    Posts:
    5
    Thank you, it solves my problem !
     
  20. gdbjohnson

    gdbjohnson

    Joined:
    Dec 16, 2014
    Posts:
    40
    Just wanted to add my 2 cents that I was also getting an error trying to serialize a custom class instance. The error message I was getting was more cryptic than described above. AOT was not mentioned in my error message. However, I did see that Reflection was in the Stack Trace, so I gave it a try with success.
     
  21. Handsome-Wisely

    Handsome-Wisely

    Joined:
    Mar 20, 2013
    Posts:
    102
    i can only praise you use my mother language 你太牛逼了!

    can you tell me how do you find this method?

    thanks
     
  22. WildKidGames

    WildKidGames

    Joined:
    Mar 6, 2019
    Posts:
    3
    Addtionally, all struct type in serialization class will cause the BinaryFormatter throw JIT error, even if they have [Serializable] attribute. So dictionary cannot be serialized, since it use KeyValuePair (which is a struct) to store data.