Unity中两个独立Inventory间物品转移异常问题求助
跨Inventory物品转移问题
我有两个独立的Inventory实例,各自挂载了独立的Inventory脚本,想要实现物品从一个Inventory转移到另一个,但实际操作起来效果如同在同一个Inventory内操作——拖拽物品到另一个Inventory的槽位时,物品只是在原Inventory的槽位间交换,并没有真正转移到目标Inventory中。
当前脚本结构
InventorySlot:每个物品槽位挂载该脚本,负责检测鼠标点击、拖拽等交互操作Inventory:每个Inventory实例挂载该脚本,负责处理物品添加、槽位内物品交换逻辑
核心问题
现有逻辑无法区分拖拽物品的源Inventory和放置目标的目标Inventory,导致无论拖到哪个Inventory的槽位,都只会调用源Inventory的ChangeItemSlot方法,仅在同一个Inventory内完成槽位交换。
解决方案
1. 记录拖拽的源Inventory信息
在InventorySlot脚本中新增变量记录源Inventory实例,并在鼠标按下时赋值:
public class InventorySlot : MonoBehaviour, IDragHandler, IPointerUpHandler, IPointerDownHandler { // ... 原有变量 ... private Inventory sourceInventory; // 新增:记录拖拽物品的源Inventory // 修改OnPointerDown方法 public void OnPointerDown(PointerEventData eventData) { foreach (GameObject overObj in eventData.hovered) { if (overObj != null) { InventorySlot slot = overObj.GetComponent<InventorySlot>(); if (slot != null && slot.item != null) { tempItem = ItemObject.CreateInstance<ItemObject>(); tempItem.itemName = slot.item.itemName; tempItem.itemSprite = slot.item.itemSprite; tempItem.amount = slot.item.amount; tempItem.stackable = slot.item.stackable; selectedslotIndex = slot.slotIndex; sourceInventory = slot.inventory; // 记录源Inventory } } } cg.blocksRaycasts = false; } // ... 原有方法 ... }
2. 在鼠标抬起时区分源/目标Inventory
修改OnPointerUp方法,判断源Inventory和目标Inventory是否为同一实例,分别执行槽位交换或跨Inventory转移逻辑:
public void OnPointerUp(PointerEventData eventData) { bool foundSlot = false; foreach (GameObject overObj in eventData.hovered) { if (overObj != null) { foundSlot = true; selectedRectTransform.anchoredPosition = Vector3.zero; InventorySlot targetSlot = overObj.GetComponent<InventorySlot>(); if (targetSlot != null) { Inventory targetInventory = targetSlot.inventory; changedSlotIndex = targetSlot.slotIndex; // 同Inventory内:执行槽位交换 if (sourceInventory == targetInventory) { sourceInventory.ChangeItemSlot(selectedslotIndex, changedSlotIndex); } // 跨Inventory:执行物品转移 else { ItemObject movedItem = sourceInventory.inventory[selectedslotIndex]; if (movedItem == null) return; // 复用AddItem逻辑处理堆叠/空位 GameObject tempGroundItem = new GameObject("TempGroundItem"); GroundItem tempGroundComp = tempGroundItem.AddComponent<GroundItem>(); tempGroundComp.item = movedItem; targetInventory.AddItem(tempGroundItem); // 清空源Inventory的对应槽位并更新显示 sourceInventory.inventory[selectedslotIndex] = null; sourceInventory.inventoryDisplay.UpdateSlots(); Destroy(tempGroundItem); } } } } if (!foundSlot) { // 原有丢弃物品逻辑不变,替换为sourceInventory操作 tempItemGameObject = Instantiate(groundItemPrefab); tempItemGameObject.GetComponent<GroundItem>().item = tempItem; tempItemGameObject.transform.position = player.transform.position + new Vector3(2f,0f,0f); selectedRectTransform.anchoredPosition = Vector3.zero; sourceInventory.inventory[selectedslotIndex] = null; sourceInventory.inventoryDisplay.UpdateSlots(); } cg.blocksRaycasts = true; }
3. 修复Inventory的槽位交换逻辑错误
原ChangeItemSlot方法中对changedSlotIndex的范围判断有误,修正如下:
public class Inventory : MonoBehaviour { // ... 原有变量 ... public void ChangeItemSlot(int selectedSlotIndex, int changedSlotIndex) { // 修正条件:确保两个索引都在Inventory范围内 if (selectedSlotIndex >= 0 && selectedSlotIndex < inventory.Count && changedSlotIndex >= 0 && changedSlotIndex < inventory.Count) { ItemObject temp = inventory[selectedSlotIndex]; inventory[selectedSlotIndex] = inventory[changedSlotIndex]; inventory[changedSlotIndex] = temp; inventoryDisplay.UpdateSlots(); } } // ... 原有方法 ... }
逻辑说明
- 通过比较
sourceInventory和targetInventory的实例对象,精准区分同Inventory交换与跨Inventory转移场景 - 跨转移时复用现有
AddItem逻辑,自动处理物品堆叠和空位判断,减少重复代码 - 确保源Inventory在转移后清空对应槽位并更新UI显示
内容的提问来源于stack exchange,提问作者erdem.61
相关产品推荐
相关产品推荐

