невозможно десериализовать данные

Я начал создавать игру 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. Это поток игры:

  1. Данные созданы.
  2. Данные сериализованы.
  3. Сериализованные данные передаются для шифрования (RijndaelManaged).
  4. Зашифрованные и сериализованные данные записываются в файл.
  5. Игра заканчивается
  6. Данные загружаются из файла.
  7. Данные не зашифрованы с использованием одного и того же ключа и IV (генерируются и сохраняются случайным образом)
  8. Данные десериализованы.
  9. Игра начинается

РЕДАКТИРОВАТЬ: попытка использовать проект 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. Комментирование этих двух методов не позволяет мне получать исключения, но сериализация по-прежнему не работает (все свойства пользователя "новые" )


person Camilo Terevinto    schedule 19.06.2015    source источник
comment
Вы уверены, что где-то не используете GetBuffer()? Основная причина недопустимого поля в исходных данных: 0 - это GetBuffer() (примечание: в GetBuffer() нет ничего принципиально неправильного, если вы не забываете смотреть только на первые Length байта)   -  person Marc Gravell    schedule 19.06.2015
comment
@MarcGravell да, я полностью уверен, что не использую GetBuffer (). Раньше я использовал его, но перешел на ToArray (), когда впервые получил эту проблему несколько недель назад.   -  person Camilo Terevinto    schedule 19.06.2015


Ответы (1)


РЕШЕНО

Оставив всякую надежду на protobuf-net, я переключился на DataCotractSerializer, который каким-то образом работал с Unity. У меня все еще было много проблем, поэтому я решил отключить шифрование и читать XML с помощью Visual Studio; с файлом все в порядке. У меня все еще было много проблем с моими 3 обработчиками событий (2 были подключены при запуске игры, другой - каждый раз, когда создается специальный объект), поэтому мне пришлось удалить обработчики событий и выполнить операции вручную (какая боль в а $$). После всего этого мне удалось снова добавить Protobuf-net, и все заработало, как должно (обратите внимание, что protobuf-net дает мне файл размером 89 байт вместо файла DCS размером 3,5 КБ)

Итак, окончательное решение этой чрезвычайно странной проблемы было:

  1. Отключить полнофункциональную реализацию RijndaelManaged
  2. Отключить все обработчики событий

Если кто-то может помочь мне понять, почему RijdnaelManaged действительно работал с Visual Studio, но не с Unity, оставьте комментарий.

person Camilo Terevinto    schedule 21.06.2015