动态寻路 A* Unity3D C#

Dynamic Pathfinding A* Unity3D C#

我正在尝试在 Unity3D 中使用 A* 寻路,如果目标保持静止,它就可以工作。但是,如果目标移动,单位仍会沿着相同的路径移动。在下面找到每个单元的代码(附加到导引头对象):

using UnityEngine;
using System.Collections;

public class Unit : MonoBehaviour {

    public Transform target;
    float speed = 20;
    Vector3[] path;
    int targetIndex;

void Start() {
    PathRequestManager.RequestPath(transform.position,target.position, OnPathFound);
}

public void OnPathFound(Vector3[] newPath, bool pathSuccessful) {
    if (pathSuccessful) {
        path = newPath;
        StopCoroutine("FollowPath");
        StartCoroutine("FollowPath");
    }
}

IEnumerator FollowPath() {
    Vector3 currentWaypoint = path[0];

    while (true) {
        if (transform.position == currentWaypoint) {
            targetIndex ++;
            if (targetIndex >= path.Length) {
                yield break;
            }
            currentWaypoint = path[targetIndex];
        }


        transform.position = Vector3.MoveTowards(transform.position,currentWaypoint,speed * Time.deltaTime);
        yield return null;

    }
}

public void OnDrawGizmos() {
    if (path != null) {
        for (int i = targetIndex; i < path.Length; i ++) {
            Gizmos.color = Color.black;
            Gizmos.DrawCube(path[i], Vector3.one);

            if (i == targetIndex) {
                Gizmos.DrawLine(transform.position, path[i]);
            }
            else {
                Gizmos.DrawLine(path[i-1],path[i]);
            }
        }
    }
}

}

现在,如果我尝试通过将 void Start() 更改为 void Update() 来将其用于动态寻路(目标移动和路径更新),这将不起作用。响应将导致奇怪的单位行为,一直来回移动或未完成路径等。 现在我不知道造成这种情况的确切原因,可能是因为协程? 无论如何,我如何更改代码才能得到正确的动态寻路结果?

提前致谢!

P.S。所有剩余的源代码都可以在这里找到: http://bit.ly/pathfindingSource

只要这个逻辑的设计不是最优的,尝试在到达下一个航路点时重新计算路径:

IEnumerator FollowPath() {
    Vector3 currentWaypoint = path[0];

    while (true) {
        if (transform.position == currentWaypoint) {

           PathRequestManager.RequestPath(transform.position,target.position, OnPathFound);

targetIndex = 0;
            targetIndex ++;
            if (targetIndex >= path.Length) {
                yield break;
            }
            currentWaypoint = path[targetIndex];
        }


        transform.position = Vector3.MoveTowards(transform.position,currentWaypoint,speed * Time.deltaTime);
        yield return null;

    }

如果你想要动态寻路,你需要在每次到达下一个路点时重新计算路径,或者有其他逻辑,比如当一些对象移动时触发一个事件 - 在处理程序中你重新计算路径。

我已经 "fixed" 解决了这个问题,现在有一个足够好的解决方案。

首先,我通过在每个航路点请求一条新路径来使寻路动态化。其次,寻路甚至在到达目标后继续进行,通过某种逻辑检查每一帧,这些单元是否再次足够远以重复协程。如果是,则停止旧的协程并启动新的协程。

代码如下:

using UnityEngine;
using System.Collections;

public class Unit : MonoBehaviour {

public Transform target;
float speed = 20;
Vector3[] path;
int targetIndex;

bool  newRequestReady;

void Start() {
    PathRequestManager.RequestPath(transform.position,target.position, OnPathFound);

    newRequestReady = false;
}

void Update(){
    float distance = Vector3.Distance (transform.position, target.position);
    Debug.Log(distance);

    if(distance < 5){
        StopCoroutine("FollowPath");
        newRequestReady = true;
    }
    else if(distance >=10 && newRequestReady){
        PathRequestManager.RequestPath(transform.position,target.position, OnPathFound);
        StopCoroutine("FollowPath");
        newRequestReady = false;

    }
}

public void OnPathFound(Vector3[] newPath, bool pathSuccessful) {
    if (pathSuccessful) {
        path = newPath;
        StopCoroutine("FollowPath");
        StartCoroutine("FollowPath");
    }
}

IEnumerator FollowPath() {
    Vector3 currentWaypoint = path[0];

    while (true) {

        if (transform.position == currentWaypoint) {
            PathRequestManager.RequestPath(transform.position,target.position,OnPathFound);
            targetIndex=0;

            targetIndex ++;
            //Debug.Log(currentWaypoint);

            if (targetIndex >= path.Length) {
                targetIndex =0;
                path = new Vector3[0];
            //yield break;
            }
            currentWaypoint = path[targetIndex];
        }
            transform.position = Vector3.MoveTowards(transform.position,currentWaypoint,speed * Time.deltaTime);

        yield return null;
    }
}


}