You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity NavMesh与AI代码问题:NPC在地图角落冻结

问题分析与修复方案

先帮你拆解下目前代码里的核心问题,以及对应的解决办法:

一、为什么IsHit函数始终返回true?

你的IsHit函数循环30次,但每次检测的都是同一个点——transform.position + transform.forward * multiplyBy,相当于重复检查同一个位置。只要这个点在可行走区域内,函数就会直接返回true,完全没尝试其他方向。这就是它永远返回true的根本原因。

二、NPC跑到角落冻结的原因

当NPC处于地图角落时,你逃跑逻辑里计算的runTo点大概率在地图外(不可行走区域),而原代码只尝试了这一个方向,找不到可行走点时没有备选逻辑,导致NavMeshAgent没有新的目标点可移动,直接停在原地冻结。


三、具体修复步骤

1. 修复IsHit函数:尝试多方向检测

修改函数逻辑,让它绕NPC旋转生成不同方向的检测点,这样才能找到周围其他可行走区域:

bool IsHit(out Vector3 result) {
    // 绕Y轴旋转360度,分成30个方向尝试
    for (int i = 0; i < 30; i++) {
        float angle = i * (360f / 30f); // 每个方向间隔12度
        Quaternion rotation = Quaternion.Euler(0, angle, 0);
        // 生成当前尝试的随机方向
        Vector3 randomDirection = rotation * (transform.position - player.position).normalized;
        Vector3 fixedPoint = transform.position + randomDirection * multiplyBy;
        
        NavMeshHit hit;
        if (NavMesh.SamplePosition(fixedPoint, out hit, 10.0f, 1 << NavMesh.GetAreaFromName("Walkable"))) {
            result = hit.position;
            return true;
        }
    }
    result = Vector3.zero;
    return false;
}

2. 修复RunFrom函数:移除无效的transform重置逻辑

原代码里先修改NPC旋转计算逃跑方向,然后立刻把位置和旋转改回初始状态,这完全是矛盾操作——等于白计算了方向。而且NavMeshAgent会自动处理移动和旋转,不需要手动修改transform:

public void RunFrom() {
    // 计算远离玩家的方向(直接用位置差,不用手动旋转transform)
    Vector3 awayDirection = (transform.position - player.position).normalized;
    Vector3 runTo = transform.position + awayDirection * multiplyBy;
    
    NavMeshHit hit;
    if(NavMesh.SamplePosition(runTo, out hit, 50, 1 << NavMesh.GetAreaFromName("Walkable"))) {
        myNMagent.SetDestination(hit.position);
    } else {
        Debug.Log("当前逃跑方向不可行,尝试其他方向");
        // 调用修复后的IsHit寻找备选点
        if(IsHit(out Vector3 validPos)) {
            myNMagent.SetDestination(validPos);
        } else {
            Debug.Log("周围无可行走区域,NPC可能被困");
        }
    }
}

3. 优化ISFacing函数(可选)

减少重复的normalized计算,让逻辑更清晰:

private bool ISFacing() {
    float angleThreshold = 45f;
    Vector3 playerForward = player.transform.forward.normalized;
    Vector3 directionToNPC = (transform.position - player.transform.position).normalized;
    float angleToPlayer = Vector3.Angle(playerForward, directionToNPC);
    return angleToPlayer < angleThreshold;
}

额外建议

  • 不要手动修改transform.position或transform.rotation,NavMeshAgent会自动处理移动和朝向,手动修改容易导致状态冲突。
  • 可以给NavMeshAgent加一个stoppingDistance,避免NPC过度贴近目标点导致卡顿。

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 07:46:23