迈向 WayPoints [C#]

Moving towards WayPoints [C#]

我遇到了这个问题:我需要敌人向目标位置移动,但我的问题是我在 Update 函数中写了这个,所以 "foreach" 语句只在一帧内完成。此外,"waypoint is reached" 语句从未显示。我该如何解决这个问题?

这是代码:`public class WayPointMovement : MonoBehaviour {

public EnemyDataSpawn enemy;
private Vector3 lastPos; 

void Start ()
{
    lastPos = gameObject.transform.position; 
}

void Update ()
{
    gameObject.transform.LookAt (LevelManager.current.playerObject.transform);
    //WaypointData is a scriptable object that contains the definition of "x" and "z" coordinates.
    foreach (WaypointData waypoints in enemy.enemy.waypoint) {
        Debug.Log (waypoints.x);
        gameObject.transform.position = Vector3.MoveTowards (gameObject.transform.position, new Vector3 (lastPos.x + waypoints.x, 0f, lastPos.z + waypoints.z), Time.deltaTime * enemy.enemy.easySpeedMovement);
        if (gameObject.transform.position.x == lastPos.x + waypoints.x && gameObject.transform.position.z == lastPos.z + waypoints.z) {
            Debug.Log("waypoint reached");
            lastPos = gameObject.transform.position;
        }
    }
}

}`

您需要返工 Update 以便它只完成一帧的工作。这意味着您必须记住 a) 您要前往哪个航路点,以及 b) 您已经走了多远。只有当您真正到达下一个航路点时,您才会继续前进。

通过waypoints有两种追踪进度的方式:

1.一旦达到,您可以简单地删除 waypoints。然后,您尝试到达的航路点始终是列表中的第一个。

2。如果你想保留 waypoints,那么你需要一个额外的变量来跟踪 当前 前往哪个 航路点。这可能类似于数组或列表的索引,或者它可能是一个枚举器 (IEnumerator<WaypointData>),每次完成一个航路点时,您都​​会在其上调用 MoveNext

您已表明(在对此答案的评论中)您不想在到达时删除 waypoints。最灵活的安排是使用索引变量:

int waypointIndex;

void Start()
{
  waypointIndex = 0;
}

void Update()
{
  if (waypointIndex < waypoints.Count)
  {
    update position;

    if (reached waypoint)
    {
      waypointIndex++;
    }
  }
}

然后,在您的 Update 方法中,您无需编写循环,而是仅更新一次游戏对象的位置,检查它是否仅到达过路点一次,如果已到达,则继续返回前的下一个航路点。如果需要多次移动才能到达一个航路点,您可以多次调用 Update;每个Update只是运动的一步。

您将需要更好的逻辑来确定何时到达航路点。正如其他评论者所指出的那样,对于浮点值,简单地检查它们是否 完全相等 不太可能起作用。相反,您可以检查到航路点的距离是否小于 Time.deltaTime * enemy.enemy.easySpeedMovement,如果是,则不使用 Vector3.MoveTowards,只需将位置准确设置为航路点,并将该步骤视为具有到达航路点。

这是粗略的逻辑(伪代码)(但不像我第一次写的那样伪代码):

Vector3 lastPos;
int waypointIndex;

void Start()
{
  lastPos = gameObject.transform.position;
  waypointIndex = 0;
}

void Update()
{
  if (waypointIndex < waypoints.Count)
  {
    waypointPosition = new Vector3 (lastPos.x + waypoints.x, 0f, lastPos.z + waypoints.z);

    if (Vector3.Distance(gameObject.transform.position, waypointPosition) > length of one step)
    {
      gameObject.transform.position = Vector3.MoveToward(gameObject.transform.position, waypointPosition);
    }
    else
    {
      gameObject.transform.position = waypointPosition;
      log("Waypoint reached");
      waypointIndex++;
    }
  }
}

使用Vector3.sqrMagnitude比较接近度。您可以定义 "close" 如何足够接近。在此示例中,我将使用航路点作为 Vector3。您可以根据自己的喜好确定航路点Vector3

// define this globally
public float closeEnough = 5f;

// Within your compare method
if((gameObject.transform.position - waypoint).sqrMagnitude < closeEnough)
{
   Debug.Log("waypoint reached");
}

注意:Vector3 - Vector3 的结果是另一个 Vector3