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

Unity C#背包系统堆叠异常:可堆叠物品无法正确入栈

问题原因与修复方案

核心问题原因

你的代码在处理可堆叠物品时,仅检查第一个背包槽位就决定是否新增槽位,没有遍历所有已存在的背包物品来寻找匹配的可堆叠项。具体来说:
在for循环内部,当第一个背包物品与当前收集物品类型不匹配时,立即执行了新增槽位的逻辑并跳出循环,完全跳过了对后续背包槽位的检查。这就导致当背包里已有多个物品时,无法找到后面的同类型可堆叠项,直接新增了槽位。

比如第四件物品收集场景:背包里有A、B两种物品,收集另一个A时,循环先检查索引0的B,发现不匹配后立刻新增A的槽位,根本没去检查索引1的A。

次要问题(潜在BUG)

直接修改ItemObject(ScriptableObject)的amount属性会修改原始资源文件,导致所有使用该物品的场景对象(比如其他地面物品)的数量都会被改变。因为ScriptableObject是共享资源,不是实例化对象。


修复后的代码

1. 修正Player脚本的物品收集逻辑

将新增槽位的逻辑移到循环结束后,确保先遍历所有背包槽位寻找可堆叠项:

[Header("Inventory")]
public int inventoryMax;
// 建议改用自定义InventoryItem类存储,避免修改ScriptableObject
public List<InventoryItem> inventory = new List<InventoryItem>();

private void OnTriggerEnter2D(Collider2D collision)
{
    if (collision.CompareTag("GroundItem"))
    {
        GroundItem groundItem = collision.GetComponent<GroundItem>();
        if (groundItem == null) return;

        if (inventory.Count < inventoryMax)
        {
            bool addedToStack = false;
            if (groundItem.item.stackable)
            {
                Debug.Log("1");
                // 遍历所有背包槽位寻找匹配项
                for (int i = 0; i < inventory.Count; i++)
                {
                    if (inventory[i].item.itemName == groundItem.item.itemName)
                    {
                        Debug.Log("2");
                        inventory[i].amount += groundItem.item.amount;
                        addedToStack = true;
                        break;
                    }
                }
            }

            // 遍历完所有槽位后,若未找到可堆叠项则新增槽位
            if (!addedToStack)
            {
                Debug.Log(inventory.Count == 0 ? "4" : "3");
                inventory.Add(new InventoryItem(groundItem.item, groundItem.item.amount));
            }

            Destroy(collision.gameObject);
        }
        else
        {
            Debug.Log("Inventory is Full");
        }
    }
}

// 新增自定义类存储背包物品实例,避免修改ScriptableObject
[System.Serializable]
public class InventoryItem
{
    public ItemObject item;
    public int amount;

    public InventoryItem(ItemObject item, int amount)
    {
        this.item = item;
        this.amount = amount;
    }
}

2. 保持ItemObject和GroundItem脚本不变

ItemObject和GroundItem脚本无需修改,但注意后续使用背包物品时,要通过InventoryItem的amount属性访问数量,而非直接修改ItemObject的amount。


内容的提问来源于stack exchange,提问作者erdem.61

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 05:32:27