SerializationException: serializationStream поддерживает поиск, но его длина равна 0 - PullRequest
0 голосов
/ 08 апреля 2019

Я использую следующий класс для сохранения и загрузки данных пользователя в / из persistentDataPath в сборке Android нашей игры Unity.Этот класс отлично работает на наших тестах из игры, но в наших инструментах Google Analytics я вижу, что у некоторых наших пользователей (около 5 КБ из 50 КБ) есть проблема, заключающаяся в том, что их данные были сброшены при входе в игру через некоторое время, и они получаютупомянутая ошибка в функции Load ().

public class GameData : MonoBehaviour
{
    private static Data _playerData;

    public static Data GetPlayerDataInstance()
    {
        Load();
        return _playerData;
    }
    public static void Save(Data data)
    {
        BinaryFormatter binaryFormatter = new BinaryFormatter();
        FileStream file = File.Create(Application.persistentDataPath + "/playerInfo.dat");

        _playerData = data;

        try
        {
            binaryFormatter.Serialize(file, data);
        }
        catch (SerializationException e)
        {
            Console.WriteLine("Failed to serialize. Reason: " + e.Message);
            throw;
        }
        finally
        {
            file.Close();
        }
    }

    public static void Drop()
    {
        if (File.Exists(Application.persistentDataPath + "/playerInfo.dat"))
        {
            print("Drop GameData");
            File.Delete(Application.persistentDataPath + "/playerInfo.dat");

            _playerData = null;

        }
        else
        {
            _playerData = null;
        }
    }

    public static void Load()
    {
        if (File.Exists(Application.persistentDataPath + "/playerInfo.dat"))
        {
            BinaryFormatter binaryFormatter = new BinaryFormatter();
            FileStream file = File.Open(Application.persistentDataPath + "/playerInfo.dat", FileMode.Open);

            Data data = null;

            try
            {
                data = (Data) binaryFormatter.Deserialize(file);
            }
            catch (SerializationException e)
            {
                 Console.WriteLine("Failed to deserialize. Reason: " + e.Message);                
                 throw;             
            }
            finally
            {                
                file.Close();
            }

            _playerData = data;
        }
        else
        {
            _playerData = null;
        }
    }
}

Когда я читаю разделы об этой ошибке, проблема почти в том, что сохраненный файл (т.е. playerInfo.dat) пуст.Как это могло случиться только с некоторыми пользователями?Есть ли решение для предотвращения этой проблемы?

ОБНОВЛЕНИЕ: Вот как выглядит реализация класса данных:

[Serializable]
public class Data
{
    public string PlayerId { get; set; }
    public string AccessToken { get; set; }

    public bool PlayMusic { get; set; }
    public bool PlaySoundEffect { get; set; }
    public bool PlayVibration { get; set; }
    public bool FinishedTutorial { get; set; }
    public bool SkippedTutorial { get; set; }
    public bool MainSceneTutorial { get; set; }
    public bool FinishedHitOpponentMohrehTutorial { get; set; }
    public bool FinishedHitByOpponentTutorial { get; set; }
    public bool FinishedEndGameExactPlaceTutorial { get; set; }
    public bool FinishedEndGameGreaterPlaceTutorial { get; set; }
    public bool FinishedEndGameLessPlaceTutorial { get; set; }
    public bool FinishedUndoButtonTutorial { get; set; }
    public bool FinishedDoubleButtonTutorial { get; set; }
    public bool FinishedDragTutorial { get; set; }
    public bool IncomingMohrehBlockedByOpponent { get; set; }
    public int ClientStickerId { get; set; }
    public int PlayCount;
    public bool FinishedTurnTimerTutorial { get; set; }

    public bool ChangedNameForEnterLeaderboard { get; set; }
    public bool LeaderboardUnlocked { get; set; }

    public PurchaseToken LastPurchaseToken { get; set; }
    public PurchaseToken LastSpinnerPurchaseToken { get; set; }

    public Data(string playerId, string accessToken)
    {
        PlayerId = playerId;
        AccessToken = accessToken;
        PlayMusic = true;
        PlaySoundEffect = true;
        PlayVibration = true;
        FinishedTutorial = false;
        SkippedTutorial = false;
        MainSceneTutorial = false;
        ClientStickerId = 0;
        LastPurchaseToken = null;
        FinishedHitOpponentMohrehTutorial = false;
        FinishedHitByOpponentTutorial = false;
        FinishedEndGameExactPlaceTutorial = false;
        FinishedEndGameGreaterPlaceTutorial = false;
        FinishedEndGameLessPlaceTutorial = false;
        IncomingMohrehBlockedByOpponent = false;
        FinishedUndoButtonTutorial = false;
        FinishedDoubleButtonTutorial = false;
        FinishedDragTutorial = false;

        ChangedNameForEnterLeaderboard = false;
        LeaderboardUnlocked = false;

        PlayCount = 1;
        FinishedTurnTimerTutorial = false;
    }
}

1 Ответ

1 голос
/ 08 апреля 2019

Не используйте свойства! ... только поля являются сериализуемыми!

после

binaryFormatter.Serialize(file, data);

вы всегда получите пустой файл.


Измените свой класс, чтобы использовать вместо него поля

[Serializable]
public class Data
{
    public string PlayerId;
    public string AccessToken;

    public bool PlayMusic;
    public bool PlaySoundEffect;
    public bool PlayVibration;
    public bool FinishedTutorial;
    public bool SkippedTutorial;
    public bool MainSceneTutorial;
    public bool FinishedHitOpponentMohrehTutorial;
    public bool FinishedHitByOpponentTutorial;
    public bool FinishedEndGameExactPlaceTutorial;
    public bool FinishedEndGameGreaterPlaceTutoria;
    public bool FinishedEndGameLessPlaceTutorial;
    public bool FinishedUndoButtonTutorial;
    public bool FinishedDoubleButtonTutorial;
    public bool FinishedDragTutorial;
    public bool IncomingMohrehBlockedByOpponent;
    public int ClientStickerId;
    public int PlayCount;
    public bool FinishedTurnTimerTutorial;

    public bool ChangedNameForEnterLeaderboard;
    public bool LeaderboardUnlocked;

    public PurchaseToken LastPurchaseToken;
    public PurchaseToken LastSpinnerPurchaseToken;

    ...
}

, где PurchaseToken также должен иметь тип Serializable.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...