在 Unity 中保存/加载数据

Posted

技术标签:

【中文标题】在 Unity 中保存/加载数据【英文标题】:Saving/loading data in Unity 【发布时间】:2017-02-25 23:18:27 【问题描述】:

我一直在搞乱在 Unity 中保存和加载,在其中我将序列化的类保存到文件中。我有一个可序列化的类:

[Serializable]
class Save

    public List<int> ID = new List<int>();
    public List<int> Amounts = new List<int>();

并将其保存到文件 A-OK。我可以毫无错误地加载它,但如果我想稍后添加:

[Serializable]
class Save

    public List<int> ID = new List<int>();
    public List<int> Amounts = new List<int>();
    public int extra = 0;

并且我运行我的脚本,它给了我一个反序列化错误,我完全理解当我将反序列化文件转换为我的新类“保存”时,我添加的新变量不存在,它给了我错误。

我在修复商店中的资产时发现了这个错误,我知道一个修复方法可以是更改文件名,以便创建一个新文件,但我不只是想擦除之前保存的内容。

所以我的问题是,如果我想在我的序列化类中添加更多变量,如果人们要更新资产,我将如何捕捉并适应它的旧版本?

谢谢!

【问题讨论】:

这是一个已知问题,我相信这个问题已经在这个网站上回答过很多次了。我只是在这个网站上找不到重复的问题,但您可以使用 Json 和 PlayerPrefs 来解决这个问题。您始终可以添加或删除项目而不会出现任何错误。 Here 是使用 Json 的示例.. 我同意@Programmer JSON 肯定比序列化好。 @Programmer 好的,很酷,所以根据我上面链接的内容,我正在使用 ONE DATA 方法。当我执行 JsonUtility.ToJson() 时,我得到一个字符串作为返回。然后我是否序列化该字符串(并放入文件中)或者您将使用什么来保存该字符串中的该信息,以便如果用户关闭游戏并重新打开我仍然将该信息保存在某处?如果我最终在我的类 Save 中添加更多内容,我会只做 JsonUtility.FromJsonOverwrite() 吗?抱歉,如果我问了太多问题,但我觉得我非常接近解决我的问题,老实说这看起来很简单。 检查我的答案。也许它让事情变得清楚了。 永远不要相信Unity3D的序列化系统。是马车!我宁愿按照程序员的建议自己编写(反)序列化器。 【参考方案1】:

这个问题在使用 C# 序列化程序时是已知的。使用JsonUtility 将数据转换为Json,然后使用PlayerPrefs 保存。加载时,使用PlayerPrefs 加载,然后使用JsonUtility 将json 转换回类。

要保存的示例类:

[Serializable]
public class Save

    public List<int> ID = new List<int>();
    public List<int> Amounts = new List<int>();
    public int extra = 0;
    public float highScore = 0;

保存数据

void Save()

    Save saveData = new Save();
    saveData.extra = 99;
    saveData.highScore = 40;

    //Convert to Json
    string jsonData = JsonUtility.ToJson(saveData);
    //Save Json string
    PlayerPrefs.SetString("MySettings", jsonData);
    PlayerPrefs.Save();

加载数据

void Load()

    //Load saved Json
    string jsonData = PlayerPrefs.GetString("MySettings");
    //Convert to Class
    Save loadedData = JsonUtility.FromJson<Save>(jsonData);

    //Display saved data
    Debug.Log("Extra: " + loadedData.extra);
    Debug.Log("High Score: " + loadedData.highScore);

    for (int i = 0; i < loadedData.ID.Count; i++)
    
        Debug.Log("ID: " + loadedData.ID[i]);
    
    for (int i = 0; i < loadedData.Amounts.Count; i++)
    
        Debug.Log("Amounts: " + loadedData.Amounts[i]);
    

JsonUtility.FromJsonJsonUtility.FromJsonOverwrite 之间的区别:

A.JsonUtility.FromJson 从 Json 创建新对象并返回它。它分配内存。

string jsonData = PlayerPrefs.GetString("MySettings");
//Convert to Class. FromJson creates new Save instance
Save loadedData = JsonUtility.FromJson<Save>(jsonData);

B.JsonUtility.FromJsonOverwrite创建新对象。它与向您的类添加更多数据类型无关。它只是覆盖其中传递的数据。它有利于节省内存和减少 GC。只有当您有arraystringList 等字段时,它才会分配内存。

应该使用JsonUtility.FromJsonOverwrite 的示例是使用Json 执行常量数据传输时。它将提高性能。

//Create Save instance **once** in the Start or Awake function
Save loadedData = null;
void Start()

    //loadedData instance is created once
    loadedData = new Save();


void Load()

    string jsonData = PlayerPrefs.GetString("MySettings");
    //Convert to Class but don't create new Save Object. Re-use loadedData and overwrite old data in it
    JsonUtility.FromJsonOverwrite(jsonData, loadedData);
    Debug.Log("High Score: " + loadedData.highScore);

【讨论】:

再次感谢程序员又一次详细的解释,让这变得像学习我的 abc 一样容易理解。 不客气。您可以在保存之前对json数据进行加密,以使玩家难以篡改保存的数据。只是谷歌“C#字符串加密”。你不应该担心这一点,但有些人会担心。编码愉快! 大声笑一点也不安全。但是加密会使它更安全。简单的加解密功能见here。如果您无法使用它,请随时提出新问题。尽管该链接上的信息很容易通过他们提供的大量示例来理解。 又一百万!! 又一百万给FromJsonOverwrite

以上是关于在 Unity 中保存/加载数据的主要内容,如果未能解决你的问题,请参考以下文章

Unity:将精灵保存/加载为 Json

Unity - 向二进制格式的保存数据添加新变量?

(Unity3D) 保存/加载玩家库存

在 IOS 中保存和加载 XML 文件会在我的 Unity 项目中产生问题

Unity保存加载功能:使用Application.persistentDataPath

C# [持久保存和加载]