我正试图制造一个人工智能对象来追逐我的玩家。播放器由用户控制。
这是我到目前为止对AI的代码,当目标处于固定位置,没有移动。我如何改变它,使我的人工智能对象追逐我的球员?
public class AstarAI : MonoBehaviour
{
//The point to move to
public Transform target;
private Seeker seeker;
//The calculated path
public Path path;
//The AI's speed per second
public float speed = 2;
//The max distance from the AI to a waypoint for it to continue to the next waypoint
public float nextWaypointDistance = 3;
//The waypoint we are currently moving towards
public int currentWaypoint = 0;
public bool arrived;
public void Start()
{
seeker = GetComponent<Seeker>();
arrived = false;
seeker.StartPath(transform.position, target.position, OnPathComplete);
}
public void OnPathComplete(Path p)
{
Debug.Log("Path calculated? " + p.error);
if (!p.error)
{
path = p;
//Reset the waypoint counter
currentWaypoint = 0;
}
}
public void FixedUpdate()
{
if (path == null)
{
//We have no path to move after yet
return;
}
if (currentWaypoint >= path.vectorPath.Count)
{
Debug.Log("End Of Path Reached");
arrived = true;
return;
}
//Direction to the next waypoint
Vector3 dir = (path.vectorPath[currentWaypoint] - transform.position).normalized;
dir *= speed * Time.fixedDeltaTime;
this.gameObject.transform.Translate(dir);
//Check if we are close enough to the next waypoint
if (Vector3.Distance(transform.position, path.vectorPath[currentWaypoint]) < nextWaypointDistance)
{
currentWaypoint++;
return;
}
}
}发布于 2018-02-01 08:57:07
您需要重新计算更新中的路由,就像您在评论中建议的那样:
public void Update()
{
GetNewPath();
}然而,如果有很多可能的搜索路径,这可能会给您的计算机带来很大的负担。我建议您调用一个更新次数较少的函数。下面是一个每秒钟重新计算路径的示例:
private const float _tickInterval = 1f
public void Start()
{
// your code
// ...
StartCoroutine(AiTick);
}
public IEnumerator AiTick();
{
while(true)
{
seeker.GetNewPath();
yield return new WaitForSeconds(_tickInterval);
}
}
public void OnDestroy()
{
StopAllCoroutines();
}在本例中,您不需要Update函数。相反,我们使用一个协同线。Coroutines是一种函数,它可以停止执行,并在以后再继续执行,然后再使用later关键字。有关更多信息,请参见文档。
在这里,它的工作如下:
public IEnumerator AiTick();是协同线。它的执行可以使用yield延迟Start中,我们称其为'StartCoroutine(AiTick);',这与调用AiTick()函数相同,但允许将其用作协同线。seeker.GetNewPath(),然后为秒停止。当它恢复为后者时,如果将到达循环的末尾,请在时间开始时返回并再次调用seeker.GetNewPath,替换更新函数,但每秒钟只执行一次OnDestroy中,我们停止协同线,因为它从来不存在。我们不需要这么做,因为这个物体无论如何都被销毁了,但是这个更干净https://stackoverflow.com/questions/48557694
复制相似问题