无法反序列化数据

unable to de-serialize data

我开始将 Unity 游戏创建为 Visual Studio 项目。我创建了一个用于测试的副项目(WinForms),因为我不知道单元测试。在那里,我的所有代码都能完美运行,即使使用的 protobuf-net DLL 是用于 Unity 的,序列化 class 也能完美运行。现在,当我开始在 Unity 上工作时,我为 protobuf-net 和 MySQL.Data 复制了我所有的代码和 DLL。出于某种原因,我无法使用(基本上)相同的代码。我在反序列化时总是得到一个异常,主要是这个:

Invalid field in source data: 0

还有这个

Unexpected end-group in source data; this usually means the source data is corrupt

这是最后一个异常的堆栈跟踪:

ProtoBuf.ProtoException: Unexpected end-group in source data; this usually means the source data is corrupt at ProtoBuf.ProtoReader.ReadFieldHeader () at (wrapper dynamic-method) NeohumanSoftware.AoN.UserInformation.User.proto_2 (object,ProtoBuf.ProtoReader) at ProtoBuf.Serializers.CompiledSerializer.ProtoBuf.Serializers.IProtoSerializer.Read (object,ProtoBuf.ProtoReader) at ProtoBuf.Meta.RuntimeTypeModel.Deserialize (int,object,ProtoBuf.ProtoReader) at ProtoBuf.Meta.TypeModel.DeserializeCore (ProtoBuf.ProtoReader,System.Type,object,bool) at ProtoBuf.Meta.TypeModel.Deserialize (System.IO.Stream,object,System.Type,ProtoBuf.SerializationContext) at ProtoBuf.Meta.TypeModel.Deserialize (System.IO.Stream,object,System.Type) at ProtoBuf.Serializer.Deserialize (System.IO.Stream) <0x000ae> at NeohumanSoftware.AoN.Storage.SerializationHandler.DeSerialize (string) <0x00140> at NeohumanSoftware.AoN.Storage.DataHandler.DeserializeUser (string)

我省略了堆栈跟踪的最后一部分,因为它不相关。我不明白为什么它在 Visual Studio 中有效,但在 Unity 中无效。这是序列化程序:

using (MemoryStream ms = new MemoryStream())
{
    Serializer.Serialize(ms, ToSerialize);
    return ms.ToArray();
}

这是反序列化器:

using (MemoryStream ms = new MemoryStream(ToDeSerialize))
{
    return Serializer.Deserialize<T>(ms);
}

这是要序列化的对象,它是游戏的 "heart",因为一切都来自 User.user:

[ProtoContract]
internal class User
{
    internal static User user { get; set; }

    [ProtoMember(1)]
    internal Something uSomething { get; private set; }
    [ProtoMember(2)]
    internal bool uSomething2 { get; set; }
    [ProtoMember(3)]
    internal Something3 uSomething3 { get; set; }
    [ProtoMember(4)]
    internal Something4 uSomething4 { get; private set; }
    [ProtoMember(5)]
    internal Something5 uSomething5 { get; private set; }

所有这些自定义 classes 都有 [ProtoContract] 属性以及至少一个 [ProtoMember],除了这两个我不使用任何其他属性。这就是游戏的流程:

  1. 数据已创建。
  2. 数据已序列化。
  3. 传递序列化数据进行加密 (RijndaelManaged)。
  4. 加密和序列化的数据被写入文件。
  5. 游戏结束
  6. 数据从文件加载。
  7. 使用完全相同的密钥和 IV(随机生成和存储)未加密数据
  8. 数据被反序列化。
  9. 游戏开始

编辑: 尝试使用 Visual Studio 的项目反序列化 Unity 的数据 NOT 行不通。尝试使用 Unity 反序列化 Visual Studio 的数据确实 NOT 有效。 Unity好像一点都不喜欢protobuf-net...

编辑2: 我将序列化器方法更改为:

byte[] b;
using (MemoryStream ms = new MemoryStream())
{
    Serializer.Serialize(ms, toXML);
    b = new byte[ms.Position];
    var fullB = ms.GetBuffer();
    Array.Copy(fullB, b, b.Length);
}

这就是我得到的:

ProtoBuf.ProtoException: Invalid wire-type; this usually means you have over-written a file without truncating or setting the length; see Using Protobuf-net, I suddenly got an exception about an unknown wire-type at ProtoBuf.ProtoReader.SkipField () at (wrapper dynamic-method) NeohumanSoftware.AoN.UserInformation.User.proto_2 (object,ProtoBuf.ProtoReader) at ProtoBuf.Serializers.CompiledSerializer.ProtoBuf.Serializers.IProtoSerializer.Read (object,ProtoBuf.ProtoReader) at ProtoBuf.Meta.RuntimeTypeModel.Deserialize (int,object,ProtoBuf.ProtoReader) at ProtoBuf.Meta.TypeModel.DeserializeCore (ProtoBuf.ProtoReader,System.Type,object,bool) at ProtoBuf.Meta.TypeModel.Deserialize (System.IO.Stream,object,System.Type,ProtoBuf.SerializationContext) at ProtoBuf.Meta.TypeModel.Deserialize (System.IO.Stream,object,System.Type) at ProtoBuf.Serializer.Deserialize (System.IO.Stream) <0x000ae>

如果有帮助,这些是读取和写入文件的方法:

internal static void SaveUser(string userSerialized)
{
    File.WriteAllText(SomePath, userSerialized);
}

internal static void LoadUser(string userSerialized)
{
    File.ReadAllText(SomePath);
}

编辑 3: 在Unity的项目中,我有这些我在Visual Studio的项目中没有的:

internal static Coordinates FromVector3(Vector3 vector)
{
    return new Coordinates(vector.x, vector.y, vector.z);
}
internal static Vector3 ToVector3(Coordinates c)
{
    return new Vector3(c.X, c.Y, c.Z);
}

这些在坐标 class 中,它有 X、Y 和 Z 的 [ProtoContract] 和 [ProtoMember]。注释掉这 2 个方法可以阻止我接收异常,但序列化仍然不起作用(用户属性都是"new")

已解决

在放弃了对 protobuf-net 的所有希望后,我切换到 DataCotractSerializer,它以某种方式在 Unity 上工作。我仍然遇到很多问题,所以我决定关闭加密并使用 Visual Studio 阅读 XML; 文件完全没问题。我的 3 个事件处理程序仍然存在很多问题(2 个在游戏开始时连接,另一个在每次创建特殊对象时连接),所以我不得不删除事件处理程序并手动执行操作(这很痛苦a$$)。 在所有这一切之后,我设法重新添加了 Protobuf-net,并且一切正常(请注意,protobuf-net 给了我一个 89 字节的文件,而不是 DCS 的 3.5 KB 文件)

所以,这个极其奇怪的问题的最终解决方案是:

  1. 禁用功能齐全的 RijndaelManaged 实施
  2. 禁用所有事件处理程序

如果有人能帮助我理解为什么 RijdnaelManaged 在 Visual Studio 而不是 Unity 上工作,请发表评论。