使用 NavMesh 寻找更近的玩家

Finding the closer player with NavMesh

在我的场景中,我的 NavMesh 位于中心(黄色的),并设置了 3 个要跟踪的立方体。我希望 NavMesh 从所有立方体中找到距离它最近且路径最短的一个并开始跟随它。我已经编写了这样做的代码,但它的行为很奇怪,我没有发现它有任何问题,但显然有问题。发生的事情是,当我单击播放并按原样保留立方体时,NavMesh 实际上会找到到最近立方体的路径并开始朝向它(立方体 3),但是当它几乎到达它时,NavMesh 很难转身开始朝立方体 1 前进,这显然不是最近的立方体。

这是我的代码。 PathLength 工作得很好。我认为问题出在 CalcPath 函数中。

float PathLength(Vector3 target){
    NavMeshPath path = new NavMeshPath ();
    myNavMesh.CalculatePath (target, path);
    int i = 1;
    float currentPathLength = 0;
    Vector3 lastCorner;
    Vector3 currentCorner;
    lastCorner = path.corners [0];

    while (i < path.corners.Length) {
        currentCorner = path.corners [i];
        currentPathLength += Vector3.Distance (lastCorner, currentCorner);
        Debug.DrawLine (lastCorner, currentCorner, Color.red,1f);
        lastCorner = currentCorner;
        i++;
    }

    return currentPathLength;
}


void CalcPath(){
    Vector3 closestTarget = Vector3.zero;
    float lastPathLength = Mathf.Infinity;
    float currentPathLength = 0;

    foreach (GameObject player in GameObject.FindGameObjectsWithTag("Player")) {

        currentPathLength = PathLength (player.transform.position);

        if (currentPathLength < lastPathLength) {
            closestTarget = player.transform.position;
        }

        lastPathLength = currentPathLength;
    }

    myNavMesh.SetDestination (closestTarget);
}

我正在比较当前路径长度和上一个路径长度,而不是存储最短路径并进行比较。我设置了一个名为 "closestTargetLength" 的新变量,并将其与当前路径长度进行了比较,效果非常好。

float PathLength(Vector3 target){
    NavMeshPath path = new NavMeshPath ();
    myNav.CalculatePath (target, path);
    int i = 1;
    float currentPathLength = 0;
    Vector3 lastCorner;
    Vector3 currentCorner;

    lastCorner = path.corners [0];
    while (i < path.corners.Length) {
        currentCorner = path.corners [i];
        currentPathLength += Vector3.Distance (lastCorner, currentCorner);
        Debug.DrawLine (lastCorner, currentCorner, Color.red);
        lastCorner = currentCorner;
        i++;
    }

    return currentPathLength;
}


void CalcPath(){
    Vector3 closestTarget = Vector3.zero;
    float closestTargetLength = Mathf.Infinity;
    float lastPathLength = Mathf.Infinity;
    float currentPathLength = 0;

    foreach (GameObject player in GameObject.FindGameObjectsWithTag("Player")) {

        currentPathLength = PathLength (player.transform.position);

        if (currentPathLength < closestTargetLength) {
            closestTarget = player.transform.position;
            closestTargetLength = currentPathLength;
        }
        lastPathLength = currentPathLength;
    }

    myNav.SetDestination (closestTarget);
}

您在 CalcPath 中确实遇到了问题。我将尝试举一个例子来告诉你什么是错的。假设到玩家的距离如下:[5,20,10]。显然玩家 A 最接近,但 CalcPath 将 return 玩家 C。我将通过你的循环来说明原因:

第一次迭代:
currentPathLength : 0 -> 5
closestTarget : null -> PlayerA.transform.position
lastPathLength : Mathf.Infinity -> 5

第二次迭代:
currentPathLength : 5 -> 20
closestTarget : PlayerA.transform.position -> PlayerA.transform.position (不变)
lastPathLength : 5 -> 20

第三次迭代(这就是你的问题所在)
currentPathLength : 20 -> 10 (这​​是 lastPathLength )
closestTarget : PlayerA.transform.position -> PlayerC.transform.position
lastPathLength : 20 -> 10

要解决此问题,请存储最小路径长度而不是存储 lastPathLength,并且只有在有新的最小值时才更改 closestTarget