c# - SerializationException: serializationStream 支持查找,但它的长度为 0
问题描述
我正在使用以下类在我们的 Unity 游戏的 Android 版本中保存和加载来自 persistentDataPath 的用户数据。这个类在我们的游戏测试中完美运行,但在我们的分析工具中,我看到我们的一些用户(大约 50K 和 50K)有一个问题,即他们的数据在一段时间后进入游戏时被重置并且他们得到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;
}
}
解决方案
不要使用属性!...只有字段是可序列化的!
后
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;
...
}
wherePurchaseToken
也应该是一个Serializable
类型。