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

Unity中Inventory系统UI随角色上下移动偏移问题求助

Unity Inventory系统UI偏移问题排查

问题现象

已将Main Camera挂载到Player角色,Canvas的Render Camera设为该相机,但角色上下移动时,UI会同向偏移(速度比未跟随相机时慢),左右移动则无此问题。尝试将相机与角色分离后问题依旧。

相关脚本

inventoryUI 脚本

public class inventoryUI : MonoBehaviour
{
  private Inventory inventory;

  private int EquippedItem;

  public bool showInventory;
  public float UItimer;
  public float UItime;

  private Transform InventorySlots;
  private Transform FirstSlotPos;
  [SerializeField] private Transform ItemSlot;
  [SerializeField] private Transform EquippedItemSlot;

  public void SetInventory(Inventory i, int EquippedItem)
  {
      inventory = i;
      this.EquippedItem = EquippedItem;
      RefreshInventory();
  }


  void Awake()
  {
      InventorySlots = transform.Find("InventorySlots");
      FirstSlotPos = InventorySlots.transform.Find("FirstSlotPosition");
  }

  [SerializeField]private float SlotSize;

  public void RefreshInventory()
  {
      if (!showInventory)
          return;

      foreach (Transform child in FirstSlotPos.transform)
      {
          if ((child != FirstSlotPos))
              Destroy(child.gameObject);
      }

      int x = 0;

      foreach (ItemData i in inventory.GetInventory())
      {
          RectTransform Slot;

          if (x == EquippedItem)
              Slot = Instantiate(EquippedItemSlot, FirstSlotPos).GetComponent<RectTransform>();
          else  Slot = Instantiate(ItemSlot, FirstSlotPos).GetComponent<RectTransform>();


          Slot.gameObject.SetActive(true);
          Slot.anchoredPosition = new Vector2(x * SlotSize, FirstSlotPos.position.y);

          Image icon = Slot.transform.Find("ItemIcon").GetComponent<Image>();
          icon.sprite = i.itemIcon;

          TextMeshProUGUI item = Slot.transform.Find("ItemNameDisplay").GetComponent<TextMeshProUGUI>();
          item.SetText(i.itemName);
          item = Slot.transform.Find("ItemAmountDisplay").GetComponent<TextMeshProUGUI>();
          item.SetText(i.amount.ToString());

          x++;
      }
  }



  void Update()
  {
      if (showInventory)
      {
          InventorySlots.gameObject.SetActive(true);
          UItimer -= Time.deltaTime;
          if (UItimer <= 0)
            showInventory = false;
      }
      else InventorySlots.gameObject.SetActive(false);
  }
}

PlayerInventory 脚本

public class PlayerInventory : MonoBehaviour
{
    [SerializeField] private inventoryUI invUI;
    public Inventory inv;

    private int EquippedItem;

    void Start()
    {
        EquippedItem = 0;

        inv = new Inventory();
        invUI.SetInventory(inv, EquippedItem);
    }

    void OnTriggerEnter2D(Collider2D col)
    {
        ItemObject i = col.GetComponent<ItemObject>();

        if (i != null)
        {
            inv.AddItem(i.GetItem());
            i.DestroyItem();
        }

        invUI.SetInventory(inv, EquippedItem);
    }

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Q))
        {
            EquippedItem -= 1;
            invUI.showInventory = true;
            invUI.UItimer = invUI.UItime;
        }
        
        if (Input.GetKeyDown(KeyCode.E))
        {
            EquippedItem += 1;
            invUI.showInventory = true;
            invUI.UItimer = invUI.UItime;
        }
       

        if (EquippedItem < 0)
            EquippedItem = inv.GetInventory().Count -1;
        else if (EquippedItem >= inv.GetInventory().Count)
            EquippedItem = 0;


        invUI.SetInventory(inv, EquippedItem);

    }
}

问题原因与修复方案

核心问题

在RefreshInventory方法中,设置Slot的anchoredPosition时,Y轴错误使用了FirstSlotPos.position.y——这是世界空间坐标,而anchoredPosition需要的是相对于父RectTransform的局部锚点坐标。当角色/相机上下移动时,FirstSlotPos的世界Y坐标会变化,导致Slot的Y位置被错误更新,出现偏移。

修复步骤

  1. 修改RefreshInventory中设置anchoredPosition的代码:

    // 替换原错误代码
    Slot.anchoredPosition = new Vector2(x * SlotSize, 0);
    

    若FirstSlotPos本身是RectTransform,也可以取其锚点Y值来保持相对位置:

    RectTransform firstSlotRect = FirstSlotPos.GetComponent<RectTransform>();
    Slot.anchoredPosition = new Vector2(x * SlotSize, firstSlotRect.anchoredPosition.y);
    
  2. 额外优化建议

    • 避免在Update中每帧调用invUI.SetInventory(inv, EquippedItem),仅在装备索引变化或物品列表更新时调用,减少不必要的UI刷新
    • 检查Canvas的Render Mode:若使用Screen Space - Camera,确保Plane Distance设置合理,且相机Projection为Orthographic(2D游戏推荐)
    • 确认FirstSlotPos的RectTransform锚点和Pivot设置正确,避免自身位置异常

内容的提问来源于stack exchange,提问作者Cu be

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 06:45:35