【发布时间】:2018-02-07 16:18:10
【问题描述】:
我正在尝试为敌人编写一个 AI,以便他每秒移动到一个新的可用方格。我将他放置在地图上的某个点上,并附有脚本。因为我不希望他在每一帧都尝试选择一个新方向,所以我做了一些研究,似乎最好的选择是做一个协程,这样它就不会执行每一帧。我已经尝试了几个小时在更新功能中编写这种不同的方式,在 IEnumerator 中,打开了各种检查,但到目前为止,我的角色似乎总是像乒乓球一样弹跳或静止不动。这是我现在在协程中的代码。
IEnumerator iMove()
{
List<string> available = new List<string>();
available.Add("North");
available.Add("South");
available.Add("East");
available.Add("West");
if (tilemap.GetTile(new Vector3Int(currentX, currentY + 1, 0)) == null || tilemap.GetTile(new Vector3Int(currentX, currentY + 1, 0)).name != floor || myStack.Contains(new int[] { currentX, currentY + 1 }))
{
available.Remove("North");
}
if (tilemap.GetTile(new Vector3Int(currentX, currentY - 1, 0)) == null || tilemap.GetTile(new Vector3Int(currentX, currentY - 1, 0)).name != floor || myStack.Contains(new int[] { currentX, currentY - 1 }))
{
available.Remove("South");
}
if (tilemap.GetTile(new Vector3Int(currentX - 1, currentY, 0)) == null || tilemap.GetTile(new Vector3Int(currentX - 1, currentY, 0)).name != floor || myStack.Contains(new int[] { currentX - 1, currentY }))
{
available.Remove("West");
}
if (tilemap.GetTile(new Vector3Int(currentX + 1, currentY, 0)) == null || tilemap.GetTile(new Vector3Int(currentX + 1, currentY, 0)).name != floor || myStack.Contains(new int[] { currentX + 1, currentY }))
{
available.Remove("East");
}
if (available.Count > 0)
{
int random = Random.Range(0, (available.Count));
string direction = available[random];
Debug.Log("attempting to move..." + direction);
switch (direction)
{
case "North":
moveVector.y = 1f;
moveVector.x = 0;
currentY += 1;
break;
case "South":
moveVector.y = -1f;
moveVector.x = 0;
currentY -= 1;
break;
case "East":
moveVector.y = 0;
moveVector.x = -1f;
currentX += 1;
break;
case "West":
moveVector.y = 0;
moveVector.x = 1f;
currentX -= 1;
break;
}
Debug.Log("current goal:" + currentX + "," + currentY);
myStack.Push(new int[] { currentX, currentY });
}
else
{
int[] test = myStack.Pop();
currentX = test[0];
currentY = test[1];
}
yield return new WaitForSeconds(1);
transform.position = new Vector3Int(currentX, currentY, 0);
moveState = MoveState.Walk;
anim.SetFloat("moveX", moveVector.x);
anim.SetFloat("moveY", moveVector.y);
anim.SetBool("isMoving", true);
yield return new WaitForSeconds(1);
}
【问题讨论】:
-
您需要了解协程是如何工作的:您调用该函数并基本上说“做这个,我不在乎需要多长时间,在它运行时,继续做通常的事情(即@ 987654322@)。”它不等待它完成,它不关心你是否第二次调用协程函数(堆栈上只会有多个副本),你不能做任何事情来检查是否功能已完成。它就像产生一个子工作线程,除了它是同步的。
-
我确实了解协程,但它似乎并没有那样工作。考虑到协程包含一个等待 1 秒的命令,这个协程运行所需的最低限度是 1 秒(假设其余代码的加载时间为 0),但是当我抛出一个协程时,协程每秒执行 MULTIPLE 次调试到协程中。
-
如果您从
Update()调用它,那么是的,是的。因为栈上有多个副本。 -
好的,有道理。那么我该如何解决呢?我尝试从头开始调用重复,它从来没有碰到我放置的任何调试代码......
-
@halfheartd 能否提供启动协程的代码?