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

Unity中重叠Sprite顶层对象无法选中拖拽的问题解决

解决重叠Sprite的顶层选中与拖拽问题

核心问题原因

两个Collider完全重叠时,默认射线检测会返回碰撞顺序靠前的对象(通常是先创建的底层对象),即便你切换了选中对象的Sorting Layer,检测逻辑没更新的话还是会选中底层。

解决方案步骤

1. 修改射线检测逻辑,优先选中视觉顶层对象

不要只获取单个射线命中结果,而是获取所有命中对象,再根据SpriteRenderer的层级属性排序,选择最顶层的对象:

  • 使用Physics2D.RaycastAll获取所有被鼠标射线击中的对象
  • 筛选出带有拖拽脚本的对象
  • 按Sorting Layer优先级(数值越大层级越高)和Order in Layer排序,取排序后的第一个对象作为选中目标

2. 代码实现示例

在你的拖拽脚本中,替换点击检测部分的代码:

using UnityEngine;
using System.Collections.Generic;

public class DragNDrop : MonoBehaviour
{
    private SpriteRenderer _spriteRenderer;
    private bool _isSelected;

    void Awake()
    {
        _spriteRenderer = GetComponent<SpriteRenderer>();
    }

    void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
            Vector2 mouseWorldPos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
            // 获取所有射线命中的2D碰撞体
            RaycastHit2D[] allHits = Physics2D.RaycastAll(mouseWorldPos, Vector2.zero);

            List<DragNDrop> validDragObjects = new List<DragNDrop>();
            foreach (RaycastHit2D hit in allHits)
            {
                DragNDrop dragComp = hit.collider.GetComponent<DragNDrop>();
                if (dragComp != null)
                {
                    validDragObjects.Add(dragComp);
                }
            }

            if (validDragObjects.Count > 0)
            {
                // 按层级从高到低排序
                validDragObjects.Sort((a, b) =>
                {
                    // 先比较Sorting Layer的数值
                    int layerValCompare = SortingLayer.GetLayerValueFromID(b._spriteRenderer.sortingLayerID) 
                                        - SortingLayer.GetLayerValueFromID(a._spriteRenderer.sortingLayerID);
                    if (layerValCompare != 0)
                        return layerValCompare;
                    // 层级相同则比较Order in Layer
                    return b._spriteRenderer.sortingOrder - a._spriteRenderer.sortingOrder;
                });

                // 取消之前选中的对象状态
                if (_isSelected)
                    Deselect();

                // 选中最顶层的对象
                DragNDrop topObject = validDragObjects[0];
                topObject.Select();
            }
        }

        // 拖拽逻辑:只有选中状态才执行
        if (_isSelected && Input.GetMouseButton(0))
        {
            Vector2 newPos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
            transform.position = newPos;
        }
    }

    public void Select()
    {
        _isSelected = true;
        // 切换到顶层Sorting Layer
        _spriteRenderer.sortingLayerName = "TopLayer";
        // 绘制Line Renderer边界逻辑...
    }

    public void Deselect()
    {
        _isSelected = false;
        _spriteRenderer.sortingLayerName = "Default";
        // 隐藏Line Renderer逻辑...
    }
}

3. 额外注意事项

  • 确保你的顶层Sorting Layer(比如示例中的TopLayer)在Sorting Layer设置中优先级高于Default
  • 如果使用的是世界空间UI(而非普通Sprite),则需要改用GraphicRaycaster获取命中的UI元素,再按层级排序
  • 避免在拖拽过程中频繁切换层级,确保选中状态的层级修改在检测前完成

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 01:05:18