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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 22:07:04