unity RaycastHit详解

UnityEngine.RaycastHit 是 Unity 物理引擎中用于存储‌射线检测(Raycasting)结果‌的核心结构体。当使用 Physics.RaycastPhysics.Linecast 或 Physics.SphereCast 等方法进行碰撞检测时,如果射线与场景中的碰撞体(Collider)相交,Unity 会将相交点的详细物理信息填充到 RaycastHit 结构中。

它就像是一个“碰撞记录仪”,提供了关于“打中了什么”、“在哪里打中的”以及“表面朝向如何”等关键数据。

1. 核心属性详解

RaycastHit 包含多个只读属性,以下是开发中最常用的关键字段:

基础交互信息

  • collider‌ (Collider)
    • 被射线击中的碰撞体组件引用。通过它可以获取 GameObject (hit.collider.gameObject) 或其他组件。
  • transform‌ (Transform)
    • 被击中物体的变换组件。如果碰撞体附加了刚体,这通常指向刚体的 Transform;否则指向碰撞体所在的 GameObject 的 Transform。
  • rigidbody‌ (Rigidbody)
    • 被击中碰撞体所依附的刚体组件。如果该物体没有刚体,此值为 null
  • articulationBody‌ (ArticulationBody)
    • 被击中碰撞体所依附的关节体组件。如果没有,此值为 null

空间位置与几何信息

  • point‌ (Vector3)
    • ‌世界坐标系‌下的撞击点位置。这是射线与碰撞体表面实际接触的点。常用于生成特效(如弹孔、火花)的位置。
  • normal‌ (Vector3)
    • 撞击点处的‌表面法线‌(世界坐标系)。这是一个单位向量,垂直于碰撞表面。
    • ‌用途‌:计算反射角度(如子弹反弹)、确定物体在斜面上的滑动方向、或者判断玩家是否站在地面上(法线接近向上)。
  • distance‌ (float)
    • 从射线原点(Ray.origin)到撞击点(hit.point)的距离。
    • ‌用途‌:判断目标是否在武器射程内,或用于排序多个命中结果(最近的优先)。

UV 与纹理坐标(高级渲染用)

  • textureCoord‌ (Vector2)
    • 撞击点处的主 UV 纹理坐标。
  • textureCoord2‌ (Vector2)
    • 撞击点处的辅助 UV 纹理坐标。
  • lightmapCoord‌ (Vector2)
    • 撞击点处的光照贴图 UV 坐标。
  • barycentricCoordinate‌ (Vector3)
    • 命中三角形的重心坐标。用于更精细地插值计算命中点在三角形内的具体位置。
  • triangleIndex‌ (int)
    • 被命中的网格三角形的索引。结合 Mesh 数据可以获取更底层的几何信息。

其他

  • colliderInstanceId‌ (int)
    • 被击中碰撞体的实例 ID,用于快速比较是否击中了同一个碰撞器对象。

2. 基本用法示例

示例 1:鼠标点击拾取物体

这是最常见的用法,将屏幕上的鼠标位置转换为世界空间的射线,检测点击到的物体。

using UnityEngine;

public class RaycastClick : MonoBehaviour
{
    void Update()
    {
        // 当鼠标左键按下时
        if (Input.GetMouseButtonDown(0))
        {
            // 1. 从相机向鼠标位置发射射线
            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
            
            // 2. 定义接收结果的变量
            RaycastHit hit;

            // 3. 执行射线检测,最大距离为 100 米
            if (Physics.Raycast(ray, out hit, 100f))
            {
                // 4. 读取 RaycastHit 信息
                Debug.Log("击中了物体: " + hit.collider.name);
                Debug.Log("击中点世界坐标: " + hit.point);
                Debug.Log("表面法线: " + hit.normal);
                Debug.Log("距离相机: " + hit.distance);

                // 示例:如果击中的是敌人,造成伤害
                Enemy enemy = hit.collider.GetComponent<Enemy>();
                if (enemy != null)
                {
                    enemy.TakeDamage(10);
                }
            }
        }
    }
}

示例 2:前方障碍物检测与法线应用

用于角色控制或 AI 视线检测,利用 normal 来判断地面坡度或墙壁朝向。

using UnityEngine;

public class GroundCheck : MonoBehaviour
{
    public float checkDistance = 1.5f;

    void Update()
    {
        // 从角色脚下向下发射射线
        Ray ray = new Ray(transform.position, Vector3.down);
        RaycastHit hit;

        if (Physics.Raycast(ray, out hit, checkDistance))
        {
            // 判断法线是否朝上(即是否是地面)
            // Vector3.up 与 hit.normal 的点积接近 1 表示表面水平朝上
            if (Vector3.Dot(hit.normal, Vector3.up) > 0.7f)
            {
                Debug.Log("站在地上");
            }
            else
            {
                Debug.Log("碰到了斜坡或墙壁");
            }
        }
    }
}

3. 高级技巧与注意事项

1. 性能优化:LayerMask(层掩码)

默认情况下,Physics.Raycast 会检测所有层级的碰撞体。为了提升性能并避免误判(例如忽略触发器 Trigger 或特定背景层),应始终使用 LayerMask

// 只检测 "Enemy" 和 "Obstacle" 层
int layerMask = LayerMask.GetMask("Enemy", "Obstacle");

if (Physics.Raycast(ray, out hit, 100f, layerMask))
{
    // 处理逻辑
}

2. 穿透检测:Physics.RaycastAll

标准的 Physics.Raycast 只返回‌第一个‌(最近的)命中结果。如果需要知道射线路径上穿过的所有物体(例如子弹穿透木板击中后面的敌人),需使用 Physics.RaycastAll

RaycastHit[] hits = Physics.RaycastAll(ray, 100f);

// RaycastAll 返回的结果不一定按距离排序,建议手动排序
System.Array.Sort(hits, (x, y) => x.distance.CompareTo(y.distance));

foreach (RaycastHit hit in hits)
{
    Debug.Log($"穿透物体: {hit.collider.name}, 距离: {hit.distance}");
}

3. 2D 物理的区别

请注意,RaycastHit 仅用于 ‌3D 物理系统‌(Physics 类)。如果你使用的是 ‌2D 物理系统‌(Physics2D类),对应的结构体是 ‌RaycastHit2D‌。两者的属性略有不同(例如 RaycastHit2D 没有 rigidbody 而是 rigidbody2D,且某些属性行为因 2D 特性而异)。

4. 触发器(Trigger)

默认情况下,Physics.Raycast ‌不会‌检测到标记为 Is Trigger 的碰撞体。如果需要检测触发器,需使用 Physics.Raycast 的重载版本并指定 QueryTriggerInteraction 参数,或者使用 Physics.RaycastNonAlloc等变体。

总结

RaycastHit 是 Unity 3D 交互开发的基石。掌握其核心属性 point(位置)、normal(朝向)、distance(距离)和 collider(对象引用),并结合 LayerMask 进行优化,可以实现从简单的鼠标拾取到复杂的物理反馈等各种功能。

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

导航