Unity PointerEventData详解

UnityEngine.EventSystems.PointerEventData 是 Unity UGUI 事件系统中用于封装‌指针输入事件‌(鼠标、触摸、手写笔等)数据的核心类。它继承自 BaseEventData,作为参数传递给各种指针相关的事件接口(如 IPointerClickHandlerIDragHandlerIScrollHandler 等),提供了关于当前指针状态的详细信息。

以下是 PointerEventData 的详细解析:

1. 核心作用

  • ‌数据载体‌:承载用户通过鼠标点击、触摸屏触摸或手柄模拟指针时产生的所有上下文信息。
  • ‌状态追踪‌:记录指针从按下、移动、拖拽到抬起的整个生命周期中的关键状态。
  • ‌射线检测信息‌:包含指针当前指向的 UI 对象或 3D 对象的射线检测结果(RaycastResult)。

2. 常用属性详解

位置与移动

  • position‌ (Vector2):当前指针在屏幕空间中的坐标位置。
  • pressPosition‌ (Vector2):指针最后一次按下(OnPointerDown)时的屏幕坐标。常用于计算拖拽起始点。
  • delta‌ (Vector2):自上一帧以来指针的移动增量。在 OnDrag 事件中非常有用,用于实现物体跟随鼠标移动。
  • scrollDelta‌ (Vector2):自上一帧以来的滚动增量(通常用于鼠标滚轮或触控板双指滑动)。

点击与按钮

  • button‌ (InputButton):触发当前事件的鼠标按钮类型(左键、右键、中键)。
  • clickCount‌ (int):连续点击的次数。可用于区分单击、双击或多击。
  • clickTime‌ (float):上次发送单击事件的时间戳。
  • pointerId‌ (int):指针的唯一标识符。
    • -1:鼠标左键
    • -2:鼠标右键
    • -3:鼠标中键
    • >= 0:触摸屏的触摸点 ID(支持多点触控)

交互对象与射线检测

  • pointerCurrentRaycast‌ (RaycastResult):当前帧指针射线检测到的结果。包含 hit 的对象、距离、UV 坐标等信息。
  • pointerPressRaycast‌ (RaycastResult):指针按下时(OnPointerDown)射线检测到的结果。即使指针移开,该值仍保留,用于判断拖拽是否仍在有效范围内。
  • pointerEnter‌ (GameObject):当前指针悬停在其上的 GameObject(即接收了 OnPointerEnter 的对象)。
  • pointerPress‌ (GameObject):接收了 OnPointerDown 事件的 GameObject。
  • pointerDrag‌ (GameObject):当前正在接收 OnDrag 事件的 GameObject。
  • hovered‌ (List<GameObject>):指针当前悬停的所有对象的列表(按层级排序)。
  • rawPointerPress‌ (GameObject):最初被按下的对象,即使它没有实现 IPointerDownHandler 接口。

状态标志

  • dragging‌ (bool):指示当前是否正在进行拖拽操作。
  • useDragThreshold‌ (bool):指示是否应应用拖动阈值(即移动超过一定像素才算拖拽)。
  • eligibleForClick‌ (bool):指示当前指针状态是否符合触发点击事件的条件(例如,没有发生大幅度的拖拽)。

3. 常用方法

  • IsPointerMoving()‌:返回布尔值,指示指针在当前帧是否有移动(基于 delta 的大小)。
  • IsScrolling()‌:返回布尔值,指示是否有滚动输入。
  • Use()‌:标记该事件已被使用。如果事件被标记为已使用,后续的 UI 元素将不再响应此事件(用于事件冒泡拦截)。
  • Reset()‌:重置事件数据到初始状态,通常由事件系统内部调用以复用对象池。

4. 代码使用示例

示例 1:获取点击位置和按钮类型

 1 using UnityEngine;
 2 using UnityEngine.EventSystems;
 3 
 4 public class ClickInfo : MonoBehaviour, IPointerClickHandler
 5 {
 6     public void OnPointerClick(PointerEventData eventData)
 7     {
 8         Debug.Log($"点击位置: {eventData.position}");
 9         Debug.Log($"点击按钮: {eventData.button}");
10         Debug.Log($"点击次数: {eventData.clickCount}");
11         
12         // 判断是否是左键双击
13         if (eventData.button == PointerEventData.InputButton.Left && eventData.clickCount == 2)
14         {
15             Debug.Log("左键双击!");
16         }
17     }
18 }

 

示例 2:实现拖拽功能

 1 using UnityEngine;
 2 using UnityEngine.EventSystems;
 3 
 4 public class DraggableItem : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler
 5 {
 6     public void OnBeginDrag(PointerEventData eventData)
 7     {
 8         Debug.Log("开始拖拽");
 9     }
10 
11     public void OnDrag(PointerEventData eventData)
12     {
13         // 使用 delta 移动物体,或者直接使用 position 设置新位置
14         // 这里演示将 UI 元素跟随鼠标移动
15         RectTransform rectTransform = GetComponent<RectTransform>();
16         rectTransform.anchoredPosition += eventData.delta;
17     }
18 
19     public void OnEndDrag(PointerEventData eventData)
20     {
21         Debug.Log("结束拖拽");
22     }
23 }

 

示例 3:判断指针 ID(区分鼠标和触摸)

 1 using UnityEngine;
 2 using UnityEngine.EventSystems;
 3 
 4 public class PointerIdentifier : MonoBehaviour, IPointerDownHandler
 5 {
 6     public void OnPointerDown(PointerEventData eventData)
 7     {
 8         int id = eventData.pointerId;
 9         if (id < 0)
10         {
11             Debug.Log("鼠标操作: " + eventData.button);
12         }
13         else
14         {
15             Debug.Log("触摸操作, 触摸点ID: " + id);
16         }
17     }
18 }

 

5. 注意事项

  1. ‌依赖 EventSystem‌:PointerEventData 由 EventSystem 生成和管理。场景中必须存在 EventSystem 对象,且通常配合 StandaloneInputModule 或 TouchInputModule 使用。
  2. ‌射线检测要求‌:为了让 UI 元素接收 PointerEventData,它们必须位于 Canvas 下,并且通常需要有 GraphicRaycaster(对于 UI)或 PhysicsRaycaster(对于 3D 对象)。UI 元素本身通常需要是 Graphic(如 Image, Text)或其子物体。
  3. ‌对象池复用‌:Unity 内部会对 PointerEventData 进行对象池管理。不要在协程或异步操作中保存对该对象的引用,因为在下一次事件发生时,该对象的数据可能会被重置或覆盖。如果需要保存数据,应复制其值(如 positiondelta 等)。
  4. ‌坐标系统‌:position 和 pressPosition 通常是屏幕空间坐标(像素),在使用时需注意与 UI 局部坐标或世界坐标的转换。

posted on 2026-05-09 14:03  -冷夜-  阅读(69)  评论(0)    收藏  举报

导航