Unity:按压状态下鼠标/手指划过Sprite检测方案及代码问题求助
解决按住鼠标/手指划过Sprite时触发事件的问题
你之前的实现有两个核心问题:一是用3D射线检测处理2D Sprite,导致命中逻辑失效;二是误用了仅检测按下瞬间的Input.GetMouseButtonDown(0),而非持续按住的状态检测。下面给你两种针对性的解决方案:
方案一:按住时划过Sprite仅触发一次(进入时执行操作)
适合“按住后移动到Sprite上就完成一次操作”的场景,比如你需求里隐藏物体的逻辑:
public class Hand : MonoBehaviour { // 标记本次按住过程中是否已触发过事件,避免重复执行 private bool _hasTriggeredDuringHold = false; private void Update() { // 检测鼠标左键/手指是否处于持续按住状态 if (Input.GetMouseButton(0)) { // 将屏幕坐标转换为2D世界坐标,用于射线检测 Vector2 worldMousePos = Camera.main.ScreenToWorldPoint(Input.mousePosition); // 发射2D射线(方向不影响,仅检测当前位置的碰撞体) RaycastHit2D hit = Physics2D.Raycast(worldMousePos, Vector2.zero); // 检查射线是否命中当前Sprite的碰撞体 if (hit.collider != null && hit.collider.gameObject == gameObject) { if (!_hasTriggeredDuringHold) { // 执行你的目标逻辑,比如隐藏物体 gameObject.SetActive(false); _hasTriggeredDuringHold = true; } } else { // 鼠标离开Sprite时重置标记,下次进入可重新触发 _hasTriggeredDuringHold = false; } } else { // 松开鼠标时重置标记,为下一次按住操作做准备 _hasTriggeredDuringHold = false; } } }
方案二:按住期间只要在Sprite上就持续触发
如果需要按住时在Sprite上移动的全程都执行逻辑(比如持续更新状态或播放动画),可以简化代码去掉触发标记:
public class Hand : MonoBehaviour { private void Update() { if (Input.GetMouseButton(0)) { Vector2 worldMousePos = Camera.main.ScreenToWorldPoint(Input.mousePosition); RaycastHit2D hit = Physics2D.Raycast(worldMousePos, Vector2.zero); if (hit.collider != null && hit.collider.gameObject == gameObject) { // 这里写你需要持续执行的逻辑 Debug.Log("按住并停留在Sprite上"); } } } }
关键注意事项
- 给Sprite添加2D碰撞体:必须给你的Sprite组件添加
BoxCollider2D(或其他2D碰撞体)并启用,这是射线检测能命中的前提。 - 切换到2D物理检测:之前你用的
Physics.Raycast是3D射线,Sprite属于2D对象,必须用Physics2D.Raycast才能正确检测碰撞。 - 区分输入检测方法:
Input.GetMouseButton(0)检测的是持续按住状态,而Input.GetMouseButtonDown(0)仅在按下的第一帧触发——这正是你之前代码无法满足需求的核心原因。
内容的提问来源于stack exchange,提问作者Keith Power
相关产品推荐
相关产品推荐

