Unity RaycastResult 说明
UnityEngine.EventSystems.RaycastResult 是 Unity UGUI 事件系统中的一个结构体(struct),用于存储和描述来自 BaseRaycaster(如 GraphicRaycaster、PhysicsRaycaster 等)的射线检测命中结果。
当用户与 UI 或 3D 对象交互时,EventSystem 会发射射线,RaycastResult 记录了射线击中的具体信息,包括击中的对象、位置、距离以及排序信息等。它是 PointerEventData 中 pointerCurrentRaycast 和 pointerPressRaycast 等属性的数据类型。
1. 核心属性详解
命中对象与信息
-
gameObject (GameObject)- 射线实际击中的 GameObject 对象。这是最常用的属性,用于获取被点击或悬停的具体游戏物体。
-
isValid (bool)- 指示该结果是否有效。如果存在关联的模块(module)且击中了有效的 GameObject,则为
true;否则为false。常用于判断射线是否真的打到了东西。
- 指示该结果是否有效。如果存在关联的模块(module)且击中了有效的 GameObject,则为
-
module (BaseRaycaster)- 产生此次命中结果的射线投射器模块。例如,如果是 UI 点击,通常是
GraphicRaycaster;如果是 3D 物体点击,可能是PhysicsRaycaster。
- 产生此次命中结果的射线投射器模块。例如,如果是 UI 点击,通常是
位置与几何信息
-
worldPosition (Vector3)- 射线击中点在世界空间中的坐标位置。
-
worldNormal (Vector3)- 射线击中点表面的法线方向(世界空间)。对于 3D 物体很有用,UI 元素通常返回默认值。
-
screenPosition (Vector2)- 生成此次射线检测时的屏幕坐标位置(通常是鼠标或触摸点的位置)。
距离与深度(用于排序和优先级)
-
distance (float)- 从射线原点到击中点的距离。在 3D 场景中,这通常用于判断哪个物体离相机更近。
-
index (float)- 命中索引。由射线投射器内部使用,用于区分同一对象上的不同命中点或辅助排序。
-
depth (int)- 元素的相对深度。在 UGUI 中,这通常与 Canvas 的渲染顺序或层级有关,用于确定当多个 UI 元素重叠时,哪个应该优先响应事件。
-
sortingLayer (int)- 击中对象所在的 Sorting Layer ID。用于 UI 或 Sprite 渲染层级的排序。
-
sortingOrder (int)- 击中对象在 Sorting Layer 内的 Order in Layer。数值越大,渲染越靠前,通常也意味着在事件响应中具有更高的优先级。
2. 常用方法
-
Clear()- 重置
RaycastResult的所有字段到默认状态(清空 gameObject,距离设为无穷大等)。通常在对象池复用或手动清除数据时使用。
- 重置
-
ToString()- 返回包含当前命中结果详细信息的字符串,常用于调试日志输出。
3. 应用场景与示例
场景 1:判断点击是否有效
在处理指针事件时,首先检查 isValid 以确保射线确实击中了某个对象。
1 using UnityEngine; 2 using UnityEngine.EventSystems; 3 4 public class ClickHandler : MonoBehaviour, IPointerClickHandler 5 { 6 public void OnPointerClick(PointerEventData eventData) 7 { 8 RaycastResult result = eventData.pointerCurrentRaycast; 9 10 if (result.isValid) 11 { 12 Debug.Log("点击了对象: " + result.gameObject.name); 13 Debug.Log("点击位置: " + result.worldPosition); 14 } 15 else 16 { 17 Debug.Log("点击了空白区域"); 18 } 19 } 20 }
场景 2:自定义射线检测逻辑
你可以手动调用 GraphicRaycaster 或其他 Raycaster 来获取 RaycastResult 列表,从而实现非标准的交互逻辑(例如:穿透点击、区域选择等)。
1 using UnityEngine; 2 using UnityEngine.UI; 3 using UnityEngine.EventSystems; 4 using System.Collections.Generic; 5 6 public class CustomRaycastExample : MonoBehaviour 7 { 8 public GraphicRaycaster graphicRaycaster; 9 public Camera eventCamera; 10 11 void Update() 12 { 13 if (Input.GetMouseButtonDown(0)) 14 { 15 PointerEventData pointerData = new PointerEventData(EventSystem.current); 16 pointerData.position = Input.mousePosition; 17 18 List<RaycastResult> results = new List<RaycastResult>(); 19 graphicRaycaster.Raycast(pointerData, results); 20 21 foreach (RaycastResult result in results) 22 { 23 Debug.Log("Hit: " + result.gameObject.name + 24 " | Distance: " + result.distance + 25 " | Depth: " + result.depth); 26 } 27 } 28 } 29 }
4. 注意事项
- 结构体特性:
RaycastResult是一个结构体(Value Type),赋值时会进行拷贝。修改副本不会影响原始数据。 - UI 与 3D 的区别:
- 对于 UI (UGUI):
distance通常不是物理距离,而是用于排序的逻辑值;sortingLayer和sortingOrder对确定点击优先级至关重要。 - 对于 3D (Physics):
distance是真实的物理距离;worldNormal更有意义;sortingLayer通常为 0。
- 对于 UI (UGUI):
- 多结果处理:一次射线检测可能返回多个
RaycastResult(存储在List<RaycastResult>中),按优先级排序。EventSystem 默认只将第一个(最顶层/最近)的结果作为主要交互对象,但开发者可以遍历列表实现特殊效果(如点击穿透)。 - 性能:由于是结构体,频繁创建和销毁不会产生 GC 压力,适合在每帧的输入检测中使用。
浙公网安备 33010602011771号