我在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
回答:
我已经“修复”了这个问题,目前有一个足够好的解决方案。
首先,我通过在每个路径点请求新的路径来使路径查找动态化。其次,即使到达目标后,路径查找也会继续进行,通过一些逻辑在每帧检查单位是否再次足够远以重复协程。如果是,则停止旧的协程并启动新的协程。
以下是代码:
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; }}}