Я начал создавать игру Unity как проект Visual Studio. Я создал побочный проект (WinForms) для тестирования, так как не знаю модульного тестирования. Там весь мой код работает отлично, класс сериализации работает безупречно, даже когда используется библиотека protobuf-net для Unity. Теперь, когда я начал работать над Unity, я скопировал весь свой код и библиотеки DLL для protobuf-net и MySQL.Data. По какой-то причине я не могу заставить работать (в основном) тот же код. Я всегда получаю исключение при десериализации, в основном это:
Неверное поле в исходных данных: 0
И это
Неожиданная конечная группа в исходных данных; обычно это означает, что исходные данные повреждены
Это трассировка стека для последнего исключения:
ProtoBuf.ProtoException: неожиданная конечная группа в исходных данных; обычно это означает, что исходные данные повреждены в ProtoBuf.ProtoReader.ReadFieldHeader () в (динамический метод оболочки) NeohumanSoftware.AoN.UserInformation.User.proto_2 (объект, ProtoBuf.ProtoReader) в ProtoBuf.Serializers.CompiledSerializer.ProtoBuf.Serializers. IProtoSerializer.Read (объект, ProtoBuf.ProtoReader) в ProtoBuf.Meta.RuntimeTypeModel.Deserialize (int, object, ProtoBuf.ProtoReader) в ProtoBuf.Meta.TypeModel.DeserializeCore (ProtoBuf.Protoypereader), объект ProtoBuf.ProtoypeReader, объект System. .Meta.TypeModel.Deserialize (System.IO.Stream, объект, System.Type, ProtoBuf.SerializationContext) в ProtoBuf.Meta.TypeModel.Deserialize (System.IO.Stream, объект, System.Type) в ProtoBuf.Serializer.Deserialize (System.IO.Stream) ‹0x000ae> в NeohumanSoftware.AoN.Storage.SerializationHandler.DeSerialize (строка) ‹0x00140> в NeohumanSoftware.AoN.Storage.DataHandler.DeserializeUser (строка)
Я пропустил последнюю часть трассировки стека, поскольку она не имеет отношения к делу. Я не понимаю, почему это работает в 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);
}
И это объект для сериализации, который является «сердцем» игры, поскольку все идет от 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; }
Все эти настраиваемые классы имеют атрибут [ProtoContract] вместе по крайней мере с одним [ProtoMember], и я не использую никаких других атрибутов, кроме этих 2. Это поток игры:
- Данные созданы.
- Данные сериализованы.
- Сериализованные данные передаются для шифрования (RijndaelManaged).
- Зашифрованные и сериализованные данные записываются в файл.
- Игра заканчивается
- Данные загружаются из файла.
- Данные не зашифрованы с использованием одного и того же ключа и IV (генерируются и сохраняются случайным образом)
- Данные десериализованы.
- Игра начинается
РЕДАКТИРОВАТЬ: попытка использовать проект Visual Studio для десериализации данных Unity НЕ работает. Попытка использовать Unity для десериализации данных Visual Studio НЕ работает. Вроде Unity вообще не любит protobuf-net ...
EDIT2: я изменил метод сериализатора на:
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: недопустимый тип провода; обычно это означает, что вы перезаписали файл без усечения или установки длины; см. Используя Protobuf-net, я внезапно получил исключение о неизвестном типе провода в ProtoBuf.ProtoReader.SkipField () по адресу (динамический метод-оболочка) NeohumanSoftware.AoN.UserInformation.User.proto_2 (объект, ProtoBuf.ProtoReader) в ProtoBuf.Serializers.CompiledSerializer.ProtoBuf.Serializers.IProtoSerializer.Read (объект, ProtoBuf.ProtoReader) в ProtoBuf.ProtoReader. Десериализовать (int, объект, ProtoBuf.ProtoReader) в ProtoBuf.Meta.TypeModel.DeserializeCore (ProtoBuf.ProtoReader, System.Type, object, bool) в ProtoBuf.Meta.TypeModel.Deserialize (System.IO.Stream, object, System. Тип, ProtoBuf.SerializationContext) в ProtoBuf.Meta.TypeModel.Deserialize (System.IO.Stream, объект, System.Type) в 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);
}
Они находятся в классе Coordinates, в котором есть [ProtoContract] и [ProtoMember] для X, Y и Z. Комментирование этих двух методов не позволяет мне получать исключения, но сериализация по-прежнему не работает (все свойства пользователя "новые" )
GetBuffer()
? Основная причина недопустимого поля в исходных данных: 0 - этоGetBuffer()
(примечание: вGetBuffer()
нет ничего принципиально неправильного, если вы не забываете смотреть только на первыеLength
байта) - person Marc Gravell   schedule 19.06.2015