我正在使用一种简单的方法来对保存文件进行序列化和反序列化,如下所示
//Object that is being stored
[System.Serializable]
public class GameData{
public int units;
public int scanRange;
public int gains;
public int reputation;
public int clicks;
public Dictionary<string,bool> upgradesPurchased;
public Dictionary<string,bool> upgradesOwned;
public Dictionary<string,bool> achievementsEarned;
public GameData(int units_Int,int scan_Range,int gains_Int,int reputation_Int,int clicks_Int,Dictionary<string,bool> upgrades_Purchased,Dictionary<string,bool> upgrades_Owned,Dictionary<string,bool> achievements_Earned){
units = units_Int;
scanRange = scan_Range;
gains = gains_Int;
reputation = reputation_Int;
clicks = clicks_Int;
upgradesPurchased = upgrades_Purchased;
upgradesOwned = upgrades_Owned;
achievementsEarned = achievements_Earned;
}
}
//Method that handles saving the object
public void SaveFile(){
string destination = Application.persistentDataPath + DATA_FILE;
FileStream file;
if (File.Exists (destination)) {
file = File.OpenWrite (destination);
} else {
file = File.Create (destination);
}
GameData data = new GameData (GameManager.Instance.units,GameManager.Instance.scanRange,GameManager.Instance.gains,GameManager.Instance.reputation,GameManager.Instance.clicks,UpgradeManager.Instance.upgradesPurchased,UpgradeManager.Instance.upgradesOwned,AchievementManager.Instance.achievementsEarned);
BinaryFormatter bf = new BinaryFormatter ();
bf.Serialize (file, data);
file.Close ();
NotificationsBar.Instance.ShowNotification ("Game saved success");
}
//Method that loads the object
public void LoadFile(){
string destination = Application.persistentDataPath + DATA_FILE;
FileStream file;
if (File.Exists (destination)) {
file = File.OpenRead (destination);
} else {
UpgradeManager.Instance.FirstLoad ();
return;
}
BinaryFormatter bf = new BinaryFormatter ();
GameData data = (GameData)bf.Deserialize (file);
file.Close ();
GameManager.Instance.units = data.units;
GameManager.Instance.scanRange = data.scanRange;
GameManager.Instance.gains = data.gains;
GameManager.Instance.reputation = data.reputation;
GameManager.Instance.clicks = data.clicks;
UpgradeManager.Instance.upgradesPurchased = data.upgradesPurchased;
UpgradeManager.Instance.upgradesOwned = data.upgradesOwned;
AchievementManager.Instance.achievementsEarned = data.achievementsEarned;
Debug.Log ("Units: " + data.units);
}
这里有很多代码,但是每个人都可以清楚地看到整个系统的样子
因此,此方法的问题是在将新值添加到传递给GameData UpgradeManager.Instance.upgradesPurchased
的字典中时,在字典key not present in dictionary
中搜索数据时会出现错误
我的分析是,由于添加了新值,因此字典中存在一个偏移值,从该位置开始放置新值以及该位置曾经存在的值
当我第一次写出代码时,字典会自动填充新的值并覆盖旧的数据
对于我的意思的直观表示,可以说您进行了2次升级
Upgrade1,Upgrade2
现在已保存
现在代码更改了,您进行了3次升级
升级1,升级3,升级2
我认为会发生的是将新值添加到保存中
所以我不确定为什么会这样。...
答案 0 :(得分:1)
虽然我看不到问题的确切原因,但我建议如下:
首先,将您的保存/加载逻辑从GameData
类中删除,并将其放入SaveDataManager
类中,这样您就可以分隔责任。
从那里,您可以将GameData
类简化为struct
,使序列化/反序列化更加容易。
然后在您的主游戏类中,每当需要加载游戏时,您都可以按照以下方式进行操作:
SaveGameManger sgManager = new SaveGameManager(file);
gameData = sgManager.LoadGame()
这将使您的代码更易于维护,如果不能解决您的问题,则查找起来会容易得多。
此外,它还允许您构建单元测试以验证加载和保存逻辑的完整性。
我没有机会对其进行测试,但是您分离并重构的代码看起来像这样(尽管它需要添加一些验证检查,但不行):
using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
namespace temp
{
public class GameLoop
{
private SaveGameManager sgManager;
private GameData data;
private bool isPlaying;
public GameLoop()
{
sgManager = new SaveGameManager("MYSAVELOCATION");
data = sgManager.LoadGame();
isPlaying = true;
}
private void PlayGame()
{
while (isPlaying)
{
//All of your game code
}
}
}
public class SaveGameManager
{
private string saveFile;
private BinaryFormatter formatter;
public SaveGameManager(string file)
{
saveFile = file;
formatter = new BinaryFormatter();
}
public GameData LoadGame()
{
using (StreamReader reader = new StreamReader(saveFile))
{
return (GameData)formatter.Deserialize(reader.BaseStream);
}
}
public void SaveGame(GameData data)
{
using (StreamWriter writer = new StreamWriter(saveFile))
{
formatter.Serialize(writer.BaseStream, data);
}
}
}
[Serializable]
public struct GameData
{
public int units;
public int scanRange;
public int gains;
public int reputation;
public int clicks;
public Dictionary<string, bool> upgradesPurchased;
public Dictionary<string, bool> upgradesOwned;
public Dictionary<string, bool> achievementsEarned;
}
}
我真的会考虑使用您的string
键进行升级,以支持枚举……更不容易出错。