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

Unity3D玩家库存存读异常:加载后库存为空问题求助

问题分析与修复方案

看起来你遇到的核心问题出在库存数据的保存逻辑上,而且还有几个序列化相关的小坑需要填上。让我一步步帮你理清并修复:

1. 致命错误:InventoryData构造函数的赋值完全颠倒了

你在InventoryData的构造函数里,把空的items、itemAmounts字段赋值给了传入的inv对象,而不是把inv里的真实数据保存到InventoryData中。这直接导致你保存的文件里根本没有任何物品数据,加载自然返回空数组。

修复代码:

修改Inventory类里的InventoryData构造函数,把赋值方向反过来,并且去掉不需要序列化的UI组件(这些Unity组件无法被BinaryFormatter正确序列化):

[Serializable]
public class InventoryData {
    // 只保存核心数据:物品数组和数量数组,UI组件不需要序列化
    public int[] itemAmounts;
    public Item[] items;

    public InventoryData(Inventory inv){
        // 初始化数组长度
        items = new Item[Inventory.numItemSlots];
        itemAmounts = new int[Inventory.numItemSlots];
        
        // 把Inventory实例的数据复制到InventoryData中
        for (int i = 0; i < Inventory.numItemSlots; i++) {
            items[i] = inv.items[i];
            itemAmounts[i] = inv.itemAmounts[i];
            // 删掉UI组件的赋值,这些属于视图层,不需要持久化
        }
    }
}

2. 必要前提:确保Item类可序列化

你的Item类必须添加[Serializable]属性,否则BinaryFormatter无法序列化它。如果Item是ScriptableObject,也要记得标记:

[Serializable]
public class Item {
    public Sprite itemImage;
    public string itemName;
    // 你的其他物品字段...
}

3. 加载后手动同步UI显示

直接赋值inv.items = loadedItems不会自动刷新UI,因为UI的更新逻辑只在AddItem里触发。你需要在加载后手动遍历数组更新UI:

修改Player的Load方法:

public void Load(){
    Debug.Log ("Loading data (player / inventory)");
    float[] loadedStats = SaveLoadManager.LoadPlayer ();
    Inventory.InventoryData loadedInvData = SaveLoadInventory.LoadInventoryData();
    
    if(loadedInvData != null){
        // 赋值核心数据
        inv.items = loadedInvData.items;
        inv.itemAmounts = loadedInvData.itemAmounts;
        
        // 手动刷新UI
        for(int i = 0; i < Inventory.numItemSlots; i++){
            if(inv.items[i] != null){
                inv.itemImages[i].sprite = inv.items[i].itemImage;
                inv.itemImages[i].enabled = true;
                inv.itemAmountsText[i].text = inv.itemAmounts[i].ToString();
            } else {
                inv.itemImages[i].enabled = false;
                inv.itemAmountsText[i].text = "";
            }
        }
    }
    
    // 处理player stats的逻辑...
}

同步修改SaveLoadInventory的Load方法:

让它返回完整的InventoryData,而不是只返回items,这样能同时加载物品数量:

public static Inventory.InventoryData LoadInventoryData(){
    string savePath = Application.persistentDataPath + "/saves/player_inventory.inv";
    
    if (File.Exists(savePath)) {
        BinaryFormatter bf = new BinaryFormatter ();
        using(FileStream stream = new FileStream(savePath, FileMode.Open)){
            Inventory.InventoryData data = bf.Deserialize (stream) as Inventory.InventoryData;
            return data;
        }
    } else {
        return null;
    }
}

4. 优化保存逻辑(可选)

你当前的保存逻辑每次都会创建新文件(player1.inv、player2.inv...),如果想覆盖最新存档而不是累积文件,可以修改SaveInventory方法用固定文件名:

public static void SaveInventory(Inventory inv){
    BinaryFormatter bf = new BinaryFormatter();
    string saveDir = Application.persistentDataPath + "/saves";
    Directory.CreateDirectory(saveDir);
    string savePath = saveDir + "/player_inventory.inv"; // 固定文件名
    
    Inventory.InventoryData data = new Inventory.InventoryData(inv);
    
    // 使用using自动关闭流,更安全
    using(FileStream stream = new FileStream(savePath, FileMode.Create)){
        bf.Serialize(stream, data);
    }
}

做完这些修改后,再测试一下保存和加载流程:保存后检查存档文件是否存在,加载时确认loadedInvData.items和itemAmounts有数据,UI也能正确显示物品。

内容的提问来源于stack exchange,提问作者Kith M.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 07:45:38