Cysharp / MemoryPack

Zero encoding extreme performance binary serializer for C# and Unity.
MIT License
3.25k stars 190 forks source link

Unity AOT error #138

Closed Sarofc closed 1 year ago

Sarofc commented 1 year ago

MemoryPack 1.9.10 Unity 2021.3 lts

Code

    [Serializable]
    [MemoryPackable]
    public partial class PlayerInput
    {
        public float2 move;
        public quaternion target;
        public List<KeyRecord> keyRecords = new();
    }

    public enum EAction : byte
    {
        Ability1,
        Ability2,
        Ability3,
        Ability4,
        Ability5,
        Ability6,
    }

    public enum EActionStatus : byte
    {
        KeyDown = 0,
        keyPressing = 1,
        KeyUp = 2,
    }

    public struct KeyRecord
    {
        public EAction action;
        public EActionStatus status;
    }

Log

EngineException: Attempting to call method 'MemoryPack.Formatters.DangerousUnmanagedFormatter`1[[Saro.Gameplay.Multiplayer.KeyRecord, Assembly-CSharp, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null]]::.ctor' for which no ahead of time (AOT) code was generated.
  at System.Reflection.RuntimeConstructorInfo.InternalInvoke (System.Object obj, System.Object[] parameters, System.Boolean wrapExceptions) [0x00000] in <00000000000000000000000000000000>:0 
  at System.RuntimeType.CreateInstanceMono (System.Boolean nonPublic, System.Boolean wrapExceptions) [0x00000] in <00000000000000000000000000000000>:0 
  at System.Activator.CreateInstance (System.Type type, System.Boolean nonPublic, System.Boolean wrapExceptions) [0x00000] in <00000000000000000000000000000000>:0 
  at MemoryPack.MemoryPackFormatterProvider.CreateGenericFormatter (System.Type type, System.Boolean typeIsReferenceOrContainsReferences) [0x00000] in <00000000000000000000000000000000>:0 
  at MemoryPack.MemoryPackFormatterProvider+Cache`1[T]..cctor () [0x00000] in <00000000000000000000000000000000>:0 
  at System.Array.Empty[T] () [0x00000] in <00000000000000000000000000000000>:0 
  at MemoryPack.Formatters.ListFormatter`1[T].Serialize (MemoryPack.MemoryPackWriter& writer, System.Collections.Generic.List`1[T]& value) [0x00000] in <00000000000000000000000000000000>:0 
  at MemoryPack.MemoryPackWriter.WriteNullUnionHeader () [0x00000] in <00000000000000000000000000000000>:0 
  at MemoryPack.MemoryPackWriter.WriteNullUnionHeader () [0x00000] in <00000000000000000000000000000000>:0 
  at MemoryPack.MemoryPackFormatter`1[T].MemoryPack.IMemoryPackFormatter.Serialize (MemoryPack.MemoryPackWriter& writer, System.Object& value) [0x00000] in <00000000000000000000000000000000>:0 
  at System.Collections.ObjectModel.ReadOnlyCollection`1[T].System.Collections.IList.get_Item (System.Int32 index) [0x00000] in <00000000000000000000000000000000>:0 
  at MemoryPack.MemoryPackSerializer.Serialize (System.Type type, System.Buffers.IBufferWriter`1[System.Byte]& bufferWriter, System.Object value, MemoryPack.MemoryPackSerializerOptions options) [0x00000] in <00000000000000000000000000000000>:0 

Expected

Use SourceGenerator to gen AOT code, instead of hand write the following code.

    [UnityEngine.Scripting.Preserve]
    internal class AOT
    {
        DangerousUnmanagedFormatter<KeyRecord> formatter;
    }
neuecc commented 1 year ago

KeyRecord is an unmanaged struct, so it can usually be serialized, but in IL2CPP, you must explicitly specify MemoryPackable to give a hint of the type.

[MemoryPackable]
public partial struct KeyRecord
{
    public EAction action;
    public EActionStatus status;
}