TouchPad(单例)
TouchPad是一个底层触摸输入管理器,直接挂载在场景中的 UI 或游戏物体上,通过实现 Unity 事件系统接口(IPointerDownHandler,IDragHandler,IPointerUpHandler,IBeginDragHandler,IDropHandler,IPointerExitHandler)来接收原始指针事件,并将其转换为:
C# 事件(供外部订阅,如
ScreenDragEvent)ExecuteEvents消息(发送给碰撞体上的TouchPadMessageTarget组件)
代码解释
1.变量声明
| 接口名称 | 作用 | 回调方法 | 触发时机 |
|---|---|---|---|
IPointerDownHandler | 指针按下 | void OnPointerDown(PointerEventData eventData) | 鼠标/手指在物体上按下时 |
IBeginDragHandler | 开始拖拽 | void OnBeginDrag(PointerEventData eventData) | 按下后移动超过阈值,开始拖拽时(仅触发一次) |
IDragHandler | 拖拽中 | void OnDrag(PointerEventData eventData) | 拖拽过程中每帧触发 |
IPointerUpHandler | 指针抬起 | void OnPointerUp(PointerEventData eventData) | 鼠标/手指抬起时 |
IDropHandler | 放下 | void OnDrop(PointerEventData eventData) | 拖拽的物体被放到另一个可放置的物体上时 |
IPointerExitHandler | 指针退出 | void OnPointerExit(PointerEventData eventData) | 指针移出物体的碰撞区域时 |
2.变量声明
2.1 事件声明
Action不是 Unity 专属,它是C# 内置的委托类型,在 Unity 中用来做事件通知、方法回调、解耦代码(最常用:按钮点击、技能释放、UI 刷新、消息广播)。
Action- C# 内置的委托类型https://blog.csdn.net/LFJINNAN/article/details/160478366
(Action = 可以存方法的变量,只能存 void 方法)
可以被外部订阅的委托字段
作用:让外部脚本(如
TouchManager)订阅并接收触摸事件,而不需要通过ExecuteEvents机制。
TouchPadEventArgshttps://blog.csdn.net/LFJINNAN/article/details/160482722?spm=1001.2014.3001.5502
2.2 属性声明
| 属性 | 类型 | 说明 |
|---|---|---|
ScreenTouchPos | Vector2 | 当前触摸点的屏幕坐标(私有 set) |
ScreenDragDirection | Vector2 | 计算当前拖拽方向(当前位置 - 上一帧位置) |
WorldTouchPos | Vector3 | 屏幕坐标转世界坐标,依赖Camera.main,若相机不存在则返回Vector3.zero |
IsTouched | bool | 是否正在触摸中(按下后未抬起/退出) |
IsActive | bool | 触摸处理是否启用(可通过SetTouchActivity修改) |
CameraMain | Camera | 简写属性,返回Camera.main(每次调用都重新获取,注意性能) |
注意:
ScreenTouchPos和IsTouched只有set没有get? 实际上代码中是public Vector2 ScreenTouchPos { get; private set; },所以外部可读但不可写。Camera.main每次访问都会调用FindGameObjectsWithTag,有一定开销,但在触摸事件中调用频率较高(每帧可能多次)。可以考虑缓存。
2.3 序列化字段(Inspector 可见)
dlog:编辑器调试日志开关,在UNITY_EDITOR预处理块中使用。onlyTopCollider:是否只向最顶层的碰撞体发送消息。此值会传给tpea.SetTouch方法,由TouchPadEventArgs内部实现射线检测时使用。
[Tooltip]:仅作用于Inspector 面板,用来给变量添加鼠标悬浮提示文字
2.4 私有字段(临时变量)
| 字段 | 类型 | 作用 |
|---|---|---|
hitList | List<Collider2D> | 当前帧按下的碰撞体列表(或上一帧的列表) |
newHitList | List<Collider2D> | 新一帧的碰撞体列表(实时射线检测结果) |
tpea | TouchPadEventArgs | 复用的参数对象,减少 GC 分配 |
pointerID | int | 当前活动的指针 ID(用于多点触控过滤) |
oldPosition | Vector2 | 上一帧的屏幕坐标 |
2.4.1pointerID
pointerID确保了用户拖拽哪张牌,系统就准确响应哪张牌,即使另一根手指不小心碰到屏幕也不会造成干扰。
| 方面 | 说明 |
|---|---|
| 核心作用 | 唯一标识并追踪一个特定的触摸点 |
| 主要使用场景 | 按下时记录,拖拽/抬起的验证,多点触控隔离 |
| 取值来源 | PointerEventData.pointerId(TouchPad)或Touch.fingerId(TouchPadS) |
| 典型值示例 | 鼠标:-1 或固定值(如10);触摸第1指:0;第2指:1 |
| 不使用的后果 | 多点触控时状态混乱,拖拽目标错误 |
2.5 单例
3.单例与初始化(Awake)
单例:如果已存在实例,则销毁当前对象;否则将自己设为单例。
保证场景里 永远只能有一个该脚本对象
- 第一次加载:赋值自己为唯一实例
- 重复挂载 / 多复制物体:自动删掉多余的
4. 事件回调详细解析
4.1 OnPointerDown - 按下
通过
IsTouched确保只有第一次按下被处理(防止多点触控中第二个手指触发)。重新创建
tpea(这里产生了 GC,是潜在的优化点)。SetTouch内部进行射线检测,填充tpea.hits。使用
ExecuteEvents.Execute<TouchPadMessageTarget>向所有命中碰撞体发送PointerDown消息。记录第一个命中物体的
TouchPadMessageTarget组件到tpea.firstSelected。触发外部事件
ScreenPointerDownEvent。
