You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 03:33:30