使用 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
。
在我的场景中,我的 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
。