Unity中如何实现队伍属性、背包数据及游戏标记的存储与加载
解决方案
1. 核心前提:给每个角色配置唯一标识
所有角色的Player脚本新增固定唯一ID字段,后续所有数据匹配都基于这个ID:
public class Player : MonoBehaviour { // 每个角色配置固定不重复的ID,比如主角填"role_main",法师队友填"role_mage" public string roleId; // 原有其他属性保留 public int WP; public float spe; public Vector3 position; }
2. 重构数据结构适配多维度存储
把单角色数据扩展为全局存档根结构,同时兼容角色数据、背包、杂项标记三类需求:
using System.Collections.Generic; using UnityEngine; using System; // 单角色存档数据 [Serializable] public class CharacterSaveData { public string roleId; public int wp; public float spe; public Vector3 pos; public CharacterSaveData(Player play) { roleId = play.roleId; wp = play.WP; spe = play.spe; pos = play.transform.position; } } // 背包物品存档数据 [Serializable] public class InventoryItemData { public int itemId; public int count; } // 杂项标记存档数据(适配Unity JsonUtility序列化规则) [Serializable] public class GameFlagData { public string flagKey; public bool flagValue; } // 全局存档根结构 [Serializable] public class GameSaveData { // 所有已解锁角色的数据 public List<CharacterSaveData> characterDatas = new List<CharacterSaveData>(); // 背包数据 public List<InventoryItemData> inventoryDatas = new List<InventoryItemData>(); // 全局杂项标记(剧情进度、宝箱状态等) public List<GameFlagData> gameFlags = new List<GameFlagData>(); }
3. 重写存档读写逻辑
using System.IO; using System.Collections.Generic; using UnityEngine; public static class SaveJson { private static string SavePath => Application.dataPath + "/save.txt"; private static string TempPath => Application.dataPath + "/temp.txt"; // 全局保存方法:传入当前所有队伍角色、背包数据、全局标记 public static void Save(List<Player> teamMembers, List<InventoryItemData> inventory, List<GameFlagData> flags) { GameSaveData saveData = new GameSaveData(); // 写入所有角色数据 foreach (var player in teamMembers) { saveData.characterDatas.Add(new CharacterSaveData(player)); } // 写入背包和标记数据 saveData.inventoryDatas = inventory; saveData.gameFlags = flags; string json = JsonUtility.ToJson(saveData); File.WriteAllText(SavePath, json); Debug.Log("存档完成: " + json); } // 全局加载方法:传入当前已解锁的所有队伍角色,返回背包和标记数据 public static (List<InventoryItemData> inventory, List<GameFlagData> flags) Load(List<Player> currentTeam) { if (!File.Exists(SavePath)) { Debug.Log("无存档文件,返回默认数据"); return (new List<InventoryItemData>(), new List<GameFlagData>()); } string json = File.ReadAllText(SavePath); GameSaveData saveData = JsonUtility.FromJson<GameSaveData>(json); // 给当前已解锁角色匹配对应存档数据 foreach (var player in currentTeam) { var matchData = saveData.characterDatas.Find(data => data.roleId == player.roleId); // 匹配到数据就赋值,没匹配到说明是新解锁角色,直接用初始属性即可 if (matchData != null) { player.WP = matchData.wp; player.spe = matchData.spe; player.transform.position = matchData.pos; player.position = matchData.pos; } } Debug.Log("读档完成"); return (saveData.inventoryDatas, saveData.gameFlags); } // 临时存档逻辑扩展示例 public static void SaveTemp(List<Player> teamMembers) { GameSaveData tempData = new GameSaveData(); foreach (var player in teamMembers) { tempData.characterDatas.Add(new CharacterSaveData(player)); } string json = JsonUtility.ToJson(tempData); File.WriteAllText(TempPath, json); Debug.Log("临时存档完成"); } public static void LoadTemp(List<Player> currentTeam) { if (!File.Exists(TempPath)) { Debug.Log("无临时存档"); return; } string json = File.ReadAllText(TempPath); GameSaveData tempData = JsonUtility.FromJson<GameSaveData>(json); foreach (var player in currentTeam) { var matchData = tempData.characterDatas.Find(data => data.roleId == player.roleId); if (matchData != null) { player.WP = matchData.wp; player.spe = matchData.spe; } } File.Delete(TempPath); } }
4. 动态解锁角色适配方案
新角色解锁时直接使用预设的初始属性初始化即可,不需要做特殊处理,下次触发存档时,新角色的数据会自动加入到存档列表中,后续读档就能正常匹配。
注意事项
- 所有参与序列化的自定义类必须加
[Serializable]属性,否则Unity的JsonUtility无法正常序列化 - 角色的
roleId必须全局唯一,不能重复,否则会出现数据匹配错误 - 如果需要多存档槽位,只需要修改
SavePath的路径规则,加入槽位编号即可
内容的提问来源于stack exchange,提问作者mehmeh1
相关产品推荐
相关产品推荐

