Search code examples
c#androidunity-game-engineprotobuf-netil2cpp

Protobuf-net & IL2CPP - System.Reflection.Emit is not supported


I have a problem with the protobuf-net and Android app built with IL2CPP.

Everything worked fine when I used MONO instead of IL2CPP for development. Now I need to use IL2CPP for x64 support. I didn't know System.Reflection.Emit is not supported with IL2CPP and protobuf-net is using it.

Is there a way to make the protobuf-net work with IL2CPP?


Solution

  • I got same problem on iOS. You have to compile ProtoModel before.

    using Assembly = UnityEditor.Compilation.Assembly;
    private static void BuildMyProtoModel()
    {
        RuntimeTypeModel typeModel = TypeModel.Create();
    
        foreach (var t in GetTypes(CompilationPipeline.GetAssemblies(AssembliesType.Player)))
        {
            var contract = t.GetCustomAttributes(typeof(ProtoContractAttribute), false);
            if (contract.Length > 0)
            {
                MetaType metaType = typeModel.Add(t, true);
    
                // support ISerializationCallbackReceiver
                if (typeof(ISerializationCallbackReceiver).IsAssignableFrom(t))
                {
                    MethodInfo beforeSerializeMethod = t.GetMethod("OnBeforeSerialize");
                    MethodInfo afterDeserializeMethod = t.GetMethod("OnAfterDeserialize");
    
                    metaType.SetCallbacks(beforeSerializeMethod, null, null, afterDeserializeMethod);
                }
    
                //add unity types
                typeModel.Add(typeof(Vector2), false).Add("x", "y");
                typeModel.Add(typeof(Vector3), false).Add("x", "y", "z");
            }
        }
    
        typeModel.Compile("MyProtoModel", "MyProtoModel.dll"); //build model
        string protoSchema = typeModel.GetSchema(null);//content for .proto file, you can generate a proto file for a specific type by passing it instead of null
    }
    
    private static IEnumerable<Type> GetTypes(IEnumerable<Assembly> assemblies)
    {
        foreach (Assembly assembly in assemblies)
        {
            foreach (Type type in AppDomain.CurrentDomain.Load(assembly.name).GetTypes())
            {
                yield return type;
            }
        }
    }
    

    Copy MyProtoModel.dll from root to Plugin folder. And use like this:

    TypeModel typeModel = new MyProtoModel();
    

    I create small project Protobuf-net & Unity:

    https://github.com/koshelevpavel/UniBufExample

    https://github.com/koshelevpavel/UniBuf

    But it just experimental and it don't have any documents.

    Small example MonoBehaviour:

    https://gist.github.com/koshelevpavel/8e2d62053fc79b2bf9e2105d18b056bc