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() { } }
解决方案
问题根源
- 物品自动返回Panel1:拖拽到PlayArea时仅修改了物品位置,未将物品的父物体切换为PlayArea,导致物品仍受Panel1的布局组件(如LayoutGroup)控制,布局刷新时会把物品拉回原位置。
- 层级混乱:未在物品放入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
相关产品推荐
相关产品推荐

