You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Unity中AI多射线检测实现:添加±45°视角射线检测

实现Unity AI的±45°多射线障碍物检测

咱们直接来解决这个问题——要让AI不再只盯着正前方,得给它扩展检测视野到左右45度范围。核心思路就是同时检测三条射线:正前方、左45°、右45°,然后根据不同方向的检测结果,灵活调整AI的移动或旋转逻辑,而不是单一的“见障碍就转”。

关键逻辑梳理

  1. 生成偏移方向向量:用四元数旋转正前方向量,得到左右45度的检测方向,这比手动计算三角函数更简单可靠。
  2. 批量检测射线:把三个方向的射线放进数组循环处理,代码更整洁,后续要加更多角度也方便扩展。
  3. 优化行为优先级:优先保留原有的“追踪可拾取目标”逻辑,然后判断正前方是否有障碍,若有则尝试往左右无障碍的方向移动,只有当三个方向都被挡住时才执行旋转。

修改后的完整代码

public float speed = 5f;
public float detectionRange = 55f;
public float rayAngleOffset = 45f; // 左右偏移的角度,可按需调整

void Update()
{
    // 定义三个检测方向:正前方、左45°、右45°
    Vector3[] rayDirections = new Vector3[]
    {
        transform.forward,
        Quaternion.Euler(0, -rayAngleOffset, 0) * transform.forward,
        Quaternion.Euler(0, rayAngleOffset, 0) * transform.forward
    };

    bool frontHasObstacle = false;
    bool canMoveLeft = true;
    bool canMoveRight = true;
    RaycastHit hit;

    // 循环检测每条射线
    for (int i = 0; i < rayDirections.Length; i++)
    {
        Ray ray = new Ray(transform.position + Vector3.up, rayDirections[i]);
        if (Physics.Raycast(ray, out hit, detectionRange))
        {
            // 优先处理正前方的可拾取目标,和原逻辑保持一致
            if (hit.collider.CompareTag("Pick Up"))
            {
                Debug.DrawLine(ray.origin, hit.point, Color.red);
                transform.position = Vector3.MoveTowards(transform.position, hit.point, Time.deltaTime * speed);
                return; // 找到目标后直接执行移动,跳过后续检测
            }
            else
            {
                Debug.DrawLine(ray.origin, hit.point, Color.blue);
                // 标记对应方向存在障碍物
                if (i == 0) frontHasObstacle = true;
                else if (i == 1) canMoveLeft = false;
                else if (i == 2) canMoveRight = false;
            }
        }
        else
        {
            Debug.DrawLine(ray.origin, ray.origin + rayDirections[i] * detectionRange, Color.white);
            // 无障碍物时标记对应方向可移动
            if (i == 1) canMoveLeft = true;
            else if (i == 2) canMoveRight = true;
        }
    }

    // 处理无目标时的移动逻辑
    if (!frontHasObstacle)
    {
        // 正前方无障碍,直接前进
        transform.position += transform.forward * speed * Time.deltaTime;
    }
    else
    {
        // 正前方有障碍,优先尝试左右移动
        if (canMoveRight)
        {
            transform.position += Quaternion.Euler(0, rayAngleOffset, 0) * transform.forward * speed * Time.deltaTime;
        }
        else if (canMoveLeft)
        {
            transform.position += Quaternion.Euler(0, -rayAngleOffset, 0) * transform.forward * speed * Time.deltaTime;
        }
        else
        {
            // 左右都被挡住,才执行旋转
            transform.Rotate(0, -80 * Time.deltaTime, 0);
        }
    }
}

代码细节说明

  • 方向向量计算Quaternion.Euler(0, -rayAngleOffset, 0) * transform.forward 这句是把正前方向量绕Y轴逆时针转45度,得到左45度的检测方向;顺时针转45度则得到右45度方向,四元数旋转是Unity中处理方向偏移的标准方式。
  • 调试可视化:不同颜色的射线能帮你在Scene视图里直观看到检测范围——红色代表追踪目标,蓝色代表检测到障碍物,白色代表无障碍物的安全方向。
  • 灵活扩展:如果需要更宽的视野,比如想加±30°、±60°的射线,只需要在rayDirections数组里添加更多旋转后的方向向量即可,核心逻辑不需要改动。

内容的提问来源于stack exchange,提问作者Ruben

火山引擎 最新活动