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
相关产品推荐
相关产品推荐

