我试图为敌人编写一个AI,以便他每秒都移动到一个新的可用方块。我把他放在瓷砖地图上的一个点上,附有一个脚本。由于我不希望他每一帧都试图选择一个新的方向,我做了一些研究,看起来最好的选择就是做一个协同程序,这样它就不会发生任何事情。 t执行每一帧。我已经尝试了几个小时在更新功能中写这种不同的方式,在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);
}
答案 0 :(得分:1)
这取决于你如何启动协程。如果你开始在Update
,当然它将在每一帧开始,你将同时运行许多协同程序。
尝试只启动一次:
public void Start()
{
StartCoroutine(iMove());
}
现在,它会执行一次,所以你会看到你的玩家移动一次。如果你想重复一遍,你可以:
1)在协程中添加while循环
IEnumerator iMove()
{
while(true) // or a boolean condition that you can set yourself
{
// Your code
// ...
yield return new WaitForSeconds(1f);
}
}
这样它会等待一秒钟,回到循环的开始并再次执行
另一种可能性是在完成后再次启动协同程序:
IEnumerator iMove()
{
// Your code
// ...
yield return new WaitForSeconds(1f);
StartCoroutine(iMove());
}
最后,请注意,当您销毁游戏对象时,此协程将被销毁。您也可以致电StopAllCoroutines()