Unity 的 NavMesh Agent 在导航网格边缘出现故障

Unity's NavMesh Agent glitches on navmesh edges

我最近开始研究 AI 和 Unity 的内置寻路功能。到目前为止,我还没有遇到更大的麻烦,但昨天我导入了一个山地模型,其中有一条从底部到顶部的路径。

我的 AI 游戏对象由 Rigidbody(设置为 kinematic)、Capsule Collider 和 NavMesh Agent 组成。 我生成了 NavMesh 并将最大坡度设置为 40 度,当 AI 跟随我的玩家或沿着指定路径 (waypoints) 行走时,AI 导航得很好,但是当我尝试在 AI 半径内的 NavMesh 上选择一个随机位置时,它几秒钟后出现故障并开始摇晃,通常是在目的地靠近 NavMesh 的边缘时。 我已经拍摄了两个视频,从昨天开始我就在努力解决这个问题。

我试过完全移除刚体,更改避障设置,降低最大坡度,但到目前为止没有任何效果。

这是它的样子:

Video 1

Video 2

我用来获取随机位置的代码:

Pastebin

        void ControlRandomWander()
        {
            float pointDist = Vector3.Distance(currentWanderPos, transform.position);

            if(pointDist < 2f || currentWanderPos == Vector3.zero)
            {
                wanderWaitTimer += Time.deltaTime * 15;

                anims.LookAround(true);

                if (wanderWaitTimer >= wanderWaitTime)
                {
                    Vector3 randPos = GetRandomPositionAroundTarget(transform.position, -wanderRadius, wanderRadius);

                    NavMeshPath pth = new NavMeshPath();
                    NavMesh.CalculatePath(transform.position, randPos, agent.areaMask, pth);
                    float pathDist = 0f;

                    if (pth.status == NavMeshPathStatus.PathComplete)
                    {
                        for (int i = 0; i < pth.corners.Length - 1; i++)
                        {
                            pathDist += Vector3.Distance(pth.corners[i], pth.corners[i + 1]);
                        }

                        Debug.Log(pathDist);

                        if (pathDist <= wanderRadius)
                        {
                            currentWanderPos = randPos;

                            wanderWaitTime = Random.Range(wanderWaitMin, wanderWaitMax);

                            anims.LookAround(false);
                            wanderWaitTimer = 0;

                            MoveToPosition(randPos, true);
                        }
                    }
                }
            }
            else
            {
                if (agent.destination != currentWanderPos)
                {
                    MoveToPosition(currentWanderPos, true);
                }
            }
        }

        Vector3 GetRandomPositionAroundTarget(Vector3 pos, float minRange, float maxRange)
        {
            float offsetX = Random.Range(minRange, maxRange);
            float offsetZ = Random.Range(minRange, maxRange);

            Vector3 orgPos = pos;

            orgPos.x += offsetX;
            orgPos.z += offsetZ;

            NavMeshHit hit;
            if(NavMesh.SamplePosition(orgPos, out hit, 5f, agent.areaMask))
            {
                Debug.Log(hit.position);
                return hit.position;
            }

            Debug.Log(hit.position);

            return pos;
        }

如果能帮助解决这个问题,我将不胜感激。

原来 NavMesh.SamplePosition 没有考虑 NavMesh Agent 半径,因此 agent 永远无法到达它。

我设法通过将 hit.position 移动到边缘的代理半径的一半来修复它。

if(NavMesh.SamplePosition(orgPos, out hit, 5f, agent.areaMask))
{
     Vector3 ret = hit.position;
     Vector3 pathDir = pos - ret;
     ret += pathDir.normalized * (agent.radius / 2);

     return ret;
}