Unity:创建Card对象后如何不松鼠标直接切换至该对象响应拖拽
解决Unity 2D卡牌游戏中Deck生成Card后直接拖拽的问题
问题核心在于:Unity的鼠标事件流默认绑定到首次接收OnMouseDown事件的对象,你直接调用Card的OnMouseDrag只是单次执行方法,不会让Unity把后续拖拽事件持续发送给新生成的Card。下面是两种可行的解决方案:
方法1:让Card接管鼠标事件流
在Deck的OnMouseDown中生成Card后,先触发Card的OnMouseDown建立拖拽初始状态,再强制让Card成为鼠标事件的接收目标,后续OnMouseDrag就会自动触发。
Deck脚本代码
using UnityEngine; public class Deck : MonoBehaviour { public GameObject cardPrefab; void OnMouseDown() { // 在Deck上方生成Card(可调整偏移量适配布局) Vector3 spawnPos = transform.position + new Vector3(0, 1f, 0); GameObject newCard = Instantiate(cardPrefab, spawnPos, Quaternion.identity); Card cardComp = newCard.GetComponent<Card>(); // 触发Card的OnMouseDown,初始化拖拽状态 cardComp.OnMouseDown(); // 让EventSystem将后续鼠标事件定向到Card UnityEngine.EventSystems.EventSystem.current.SetSelectedGameObject(newCard); } }
Card脚本代码
using UnityEngine; public class Card : MonoBehaviour { private bool _isDragging; private Vector3 _mouseOffset; void OnMouseDown() { _isDragging = true; // 计算鼠标与卡片中心的偏移,避免拖拽时卡片瞬移到鼠标位置 Vector3 mouseWorldPos = Camera.main.ScreenToWorldPoint(Input.mousePosition); mouseWorldPos.z = 0; // 2D场景固定Z轴 _mouseOffset = transform.position - mouseWorldPos; } void OnMouseDrag() { if (!_isDragging) return; Vector3 mouseWorldPos = Camera.main.ScreenToWorldPoint(Input.mousePosition); mouseWorldPos.z = 0; transform.position = mouseWorldPos + _mouseOffset; } void OnMouseUp() { _isDragging = false; // 释放事件绑定 UnityEngine.EventSystems.EventSystem.current.SetSelectedGameObject(null); } }
方法2:手动模拟拖拽逻辑
如果因EventSystem冲突导致方法1失效,可以在Deck的OnMouseDown生成Card后,直接在Deck的OnMouseDrag中代理Card的移动逻辑,直到鼠标松开:
// 修改后的Deck脚本 using UnityEngine; public class Deck : MonoBehaviour { public GameObject cardPrefab; private Card _currentDraggingCard; private Vector3 _mouseOffset; void OnMouseDown() { Vector3 spawnPos = transform.position + new Vector3(0, 1f, 0); GameObject newCard = Instantiate(cardPrefab, spawnPos, Quaternion.identity); _currentDraggingCard = newCard.GetComponent<Card>(); // 初始化偏移量 Vector3 mouseWorldPos = Camera.main.ScreenToWorldPoint(Input.mousePosition); mouseWorldPos.z = 0; _mouseOffset = _currentDraggingCard.transform.position - mouseWorldPos; } void OnMouseDrag() { if (_currentDraggingCard == null) return; Vector3 mouseWorldPos = Camera.main.ScreenToWorldPoint(Input.mousePosition); mouseWorldPos.z = 0; _currentDraggingCard.transform.position = mouseWorldPos + _mouseOffset; } void OnMouseUp() { _currentDraggingCard = null; } }
注意事项
- 确保Deck和Card都有Collider2D组件(Unity的OnMouse系列事件必须依赖Collider才能触发)
- 如果是UI卡牌(基于Canvas渲染),建议改用
IPointerDownHandler、IPointerDragHandler等UGUI事件接口,适配UI事件系统
内容的提问来源于stack exchange,提问作者Weed OK
相关产品推荐
相关产品推荐

