Unity/C#:ScriptableObject数组存储JSON仅保留最后一项问题排查
问题分析与解决方案
嘿,我一眼就瞅出你代码里的问题啦!你在循环保存每个ShopItem的时候,每次都创建同一个文件skins_save.txt——File.Create()方法如果遇到已存在的文件,会直接覆盖掉原有内容,所以循环跑完后,自然就只剩最后一个对象的数据咯。
下面给你两种靠谱的解决思路:
方案1:序列化整个数组(推荐)
JsonUtility默认没法直接序列化数组,所以我们可以给数组套个包装类,一次性序列化整个集合,这样既高效又避免覆盖问题:
首先创建一个序列化的包装类:
[Serializable] public class ShopItemCollection { public ShopItem[] items; }
然后修改你的SaveGame方法:
public void SaveGame() { string saveDir = Application.persistentDataPath + "/game_save"; string dataDir = saveDir + "/data"; // 确保目录存在 if (!Directory.Exists(saveDir)) { Directory.CreateDirectory(saveDir); } if (!Directory.Exists(dataDir)) { Directory.CreateDirectory(dataDir); } string filePath = dataDir + "/skins_save.txt"; BinaryFormatter bf = new BinaryFormatter(); // 把数组装进包装类 ShopItemCollection collection = new ShopItemCollection(); collection.items = shopitems; // 序列化整个集合为JSON string json = JsonUtility.ToJson(collection, prettyPrint: true); // 使用using语句自动管理文件流,不用手动Close using (FileStream file = File.Create(filePath)) { bf.Serialize(file, json); } }
方案2:给每个对象单独命名文件
如果你确实需要每个ShopItem存成单独的文件,那只要给每个文件加个索引后缀,避免重名覆盖就行:
public void SaveGame() { string saveDir = Application.persistentDataPath + "/game_save"; string dataDir = saveDir + "/data"; if (!Directory.Exists(saveDir)) { Directory.CreateDirectory(saveDir); } if (!Directory.Exists(dataDir)) { Directory.CreateDirectory(dataDir); } BinaryFormatter bf = new BinaryFormatter(); for (int i = 0; i < shopitems.Length; i++) { ShopItem si = shopitems[i]; // 给文件名加上索引区分 string filePath = dataDir + $"/skins_save_{i}.txt"; using (FileStream file = File.Create(filePath)) { var json = JsonUtility.ToJson(si); bf.Serialize(file, json); } } }
另外补充个小建议:用using语句包裹FileStream是更好的习惯,它会在代码块结束后自动关闭并释放文件资源,比手动调用Close()更安全哦。
内容的提问来源于stack exchange,提问作者AdXxRi
相关产品推荐
相关产品推荐

