Unity RaycastResult 说明

UnityEngine.EventSystems.RaycastResult 是 Unity UGUI 事件系统中的一个结构体(struct),用于存储和描述来自 BaseRaycaster(如 GraphicRaycasterPhysicsRaycaster 等)的射线检测命中结果。

当用户与 UI 或 3D 对象交互时,EventSystem 会发射射线,RaycastResult 记录了射线击中的具体信息,包括击中的对象、位置、距离以及排序信息等。它是 PointerEventData 中 pointerCurrentRaycast 和 pointerPressRaycast 等属性的数据类型。

1. 核心属性详解

命中对象与信息

  • gameObject‌ (GameObject)
    • 射线实际击中的 GameObject 对象。这是最常用的属性,用于获取被点击或悬停的具体游戏物体。
  • isValid‌ (bool)
    • 指示该结果是否有效。如果存在关联的模块(module)且击中了有效的 GameObject,则为 true;否则为 false。常用于判断射线是否真的打到了东西。
  • module‌ (BaseRaycaster)
    • 产生此次命中结果的射线投射器模块。例如,如果是 UI 点击,通常是 GraphicRaycaster;如果是 3D 物体点击,可能是 PhysicsRaycaster

位置与几何信息

  • 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. 注意事项

  1. ‌结构体特性‌:RaycastResult 是一个结构体(Value Type),赋值时会进行拷贝。修改副本不会影响原始数据。
  2. ‌UI 与 3D 的区别‌:
    • 对于 ‌UI (UGUI)‌:distance 通常不是物理距离,而是用于排序的逻辑值;sortingLayer 和 sortingOrder 对确定点击优先级至关重要。
    • 对于 ‌3D (Physics)‌:distance 是真实的物理距离;worldNormal 更有意义;sortingLayer 通常为 0。
  3. ‌多结果处理‌:一次射线检测可能返回多个 RaycastResult(存储在 List<RaycastResult> 中),按优先级排序。EventSystem 默认只将第一个(最顶层/最近)的结果作为主要交互对象,但开发者可以遍历列表实现特殊效果(如点击穿透)。
  4. ‌性能‌:由于是结构体,频繁创建和销毁不会产生 GC 压力,适合在每帧的输入检测中使用。

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

导航