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

Unity跨面板逐次拖拽堆叠:解决物品回退与层级混乱问题

拖拽物品至目标面板的层级与归位问题解决

需求

  • 将Panel1(PlayerHand)中的物品逐个拖拽至Panel2(PlayArea),每次拖拽到Panel2的物品需显示在已有物品上方。

当前问题

  • 已实现单次拖拽,但拖拽第二个物品时,第一个会自动返回Panel1;
  • 移除代码中itemBeingDragged.transform.SetAsLastSibling()后,虽可完成全部物品拖拽,但物品层级混乱,部分显示在下层、部分在上层。

问题代码

public class Drag : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler
{
    public string playArea = "PlayArea";
    public string playerHand = "PlayerHand";

    static public GameObject itemBeingDragged;
    public Vector3 startPosition;

    public void OnBeginDrag(PointerEventData eventData)
    {
        itemBeingDragged = eventData.pointerDrag;
        itemBeingDragged.transform.SetAsLastSibling();
        startPosition = itemBeingDragged.transform.position;
        GetComponent<CanvasGroup>().blocksRaycasts = false;
    }

    public void OnDrag(PointerEventData eventData)
    {
        itemBeingDragged.transform.position = eventData.position;
    }

    public void OnEndDrag(PointerEventData eventData)
    {
        if (eventData.pointerEnter != null && eventData.pointerEnter.transform.name == playArea)
        {
            itemBeingDragged.transform.position = eventData.position;
        }
        else
        {
            itemBeingDragged.transform.position = startPosition;

        }
        GetComponent<CanvasGroup>().blocksRaycasts = true;
    }

    void Start()
    {
        
    }

    void Update()
    {
        
    }    
}

解决方案

问题根源

  1. 物品自动返回Panel1:拖拽到PlayArea时仅修改了物品位置,未将物品的父物体切换为PlayArea,导致物品仍受Panel1的布局组件(如LayoutGroup)控制,布局刷新时会把物品拉回原位置。
  2. 层级混乱:未在物品放入PlayArea后主动设置其层级,导致新拖入的物品无法确保在已有物品上方。

修改后的代码

public class Drag : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler
{
    public string playArea = "PlayArea";
    public string playerHand = "PlayerHand";

    static public GameObject itemBeingDragged;
    public Vector3 startPosition;
    private Transform originalParent; // 记录物品原始父物体

    public void OnBeginDrag(PointerEventData eventData)
    {
        itemBeingDragged = eventData.pointerDrag;
        originalParent = itemBeingDragged.transform.parent; // 保存原始父物体
        itemBeingDragged.transform.SetAsLastSibling(); // 拖拽时确保当前物品在最上层
        startPosition = itemBeingDragged.transform.position;
        GetComponent<CanvasGroup>().blocksRaycasts = false;
    }

    public void OnDrag(PointerEventData eventData)
    {
        itemBeingDragged.transform.position = eventData.position;
    }

    public void OnEndDrag(PointerEventData eventData)
    {
        if (eventData.pointerEnter != null && eventData.pointerEnter.transform.name == playArea)
        {
            // 将物品父物体切换为PlayArea,脱离原布局控制
            itemBeingDragged.transform.SetParent(eventData.pointerEnter.transform);
            itemBeingDragged.transform.position = eventData.position;
            // 设置为PlayArea子物体的最后一个,确保显示在最上层
            itemBeingDragged.transform.SetAsLastSibling();
        }
        else
        {
            // 放回原始父物体并重置位置
            itemBeingDragged.transform.SetParent(originalParent);
            itemBeingDragged.transform.position = startPosition;
            // 放回后确保在原面板的层级正确
            itemBeingDragged.transform.SetAsLastSibling();
        }
        GetComponent<CanvasGroup>().blocksRaycasts = true;
    }

    void Start()
    {
        
    }

    void Update()
    {
        
    }    
}

关键修改点

  • 添加originalParent变量记录物品的原始父物体,确保拖拽失败时能正确放回原面板;
  • 拖拽成功时,将物品父物体切换为PlayArea,彻底脱离Panel1的布局控制,避免被自动拉回;
  • 物品放入PlayArea后调用SetAsLastSibling(),保证新拖入的物品始终显示在已有物品上方;
  • 保留拖拽开始时的SetAsLastSibling(),确保拖拽过程中当前物品在视觉最上层。

内容的提问来源于stack exchange,提问作者Patrick S

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 00:43:13