Unity C#中如何存储含不规则二维数组的复杂类?
解决复杂容器类的简便序列化存储方案
核心前提:标记无需序列化的字段
先给Slot类中不需要存储的字段加上序列化忽略标记,避免手动过滤:
- 用Unity内置
JsonUtility的话,加[NonSerialized]属性 - 用Newtonsoft.Json的话,加
[JsonIgnore]属性
方法一:改进Unity内置JsonUtility(无需额外插件)
步骤1:调整类的序列化标记
修改Slot和Container类,确保可序列化:
[Serializable] public class Slot { [NonSerialized] // 忽略该字段,不参与序列化 public Container Container { get; private set; } public Vector2 Position { get; private set; } public Item Item { get; private set; } public int Capacity { get; private set; } public int Count { get; private set; } public bool IsEquipped { get; private set; } [NonSerialized] // 忽略UI引用 public SlotUI SlotUI { get; private set; } // 注意:如果属性是私有set,JsonUtility需要对应字段加[SerializeField],或者提供无参构造 // 例如Position如果是封装字段,需调整为: // [SerializeField] private Vector2 _position; // public Vector2 Position => _position; } [Serializable] public class Container { // 记录二维数组的尺寸,用于反序列化重建 public int Rows; public int Columns; // 用一维数组存储(或直接用二维数组Slot[,],JsonUtility支持) public Slot[] Slots; // 序列化整个容器为JSON public string SerializeToJson() { return JsonUtility.ToJson(this, prettyPrint: true); } // 从JSON反序列化容器 public static Container DeserializeFromJson(string json) { var container = JsonUtility.FromJson<Container>(json); // 如果用一维数组,这里可以转成二维结构(根据你的需求) // 示例: // Slot[,] slotGrid = new Slot[container.Rows, container.Columns]; // for (int i = 0; i < container.Rows; i++) // { // for (int j = 0; j < container.Columns; j++) // { // slotGrid[i, j] = container.Slots[i * container.Columns + j]; // } // } // container.SlotGrid = slotGrid; return container; } }
步骤2:结合PlayerPrefs保存/加载
// 保存容器数据 var playerContainer = GetComponent<Container>(); string containerJson = playerContainer.SerializeToJson(); PlayerPrefs.SetString("PlayerInventory", containerJson); PlayerPrefs.Save(); // 加载容器数据 string savedJson = PlayerPrefs.GetString("PlayerInventory"); if (!string.IsNullOrEmpty(savedJson)) { var loadedContainer = Container.DeserializeFromJson(savedJson); // 反序列化后手动补全忽略的字段: foreach (var slot in loadedContainer.Slots) { slot.Container = loadedContainer; // 重新绑定Container引用 // 重新绑定SlotUI:根据slot.Position找到对应的UI组件,或通过其他逻辑关联 } }
方法二:使用Newtonsoft.Json(更灵活)
如果项目允许引入第三方插件,Newtonsoft.Json对复杂结构的支持更好,无需过多调整类结构:
步骤1:安装插件
在Unity Package Manager中搜索com.unity.nuget.newtonsoft-json并安装。
步骤2:调整类标记
public class Slot { [JsonIgnore] // 忽略不需要存储的字段 public Container Container { get; private set; } public Vector2 Position { get; private set; } public Item Item { get; private set; } public int Capacity { get; private set; } public int Count { get; private set; } public bool IsEquipped { get; private set; } [JsonIgnore] public SlotUI SlotUI { get; private set; } } public class Container { public int Rows; public int Columns; public Slot[,] Slots; // 直接支持二维数组序列化 public string SerializeToJson() { return JsonConvert.SerializeObject(this, Formatting.Indented); } public static Container DeserializeFromJson(string json) { return JsonConvert.DeserializeObject<Container>(json); } }
步骤3:保存/加载逻辑
和方法一一致,只是序列化方法换成Newtonsoft的JsonConvert,反序列化后同样需要手动补全Container和SlotUI的引用。
关键注意事项
Item类也需要确保可序列化:用JsonUtility的话加[Serializable],Newtonsoft则默认支持public属性- 反序列化后必须手动恢复忽略的引用字段(如
Container、SlotUI),因为这些字段没有被存储 - 如果容器尺寸动态变化,一定要在Container中存储
Rows和Columns,否则反序列化时无法重建正确的二维数组
内容的提问来源于stack exchange,提问作者Lucky
相关产品推荐
相关产品推荐

