Enemies who follow waypoints and stop at them before continuing to next point

This is my current code, and have messed around with putting the wait statement in different lines (in the if statement mainly before calculating the next waypoint), however the enemies dont stop and wait. Also, having the yield return statements inside the if block, crashes the game. Any help here?

    IEnumerator Patrol()
         {
            state = State.Patrolling;
            while (patrolPath != null)
            {
                //Set the nextposition the character should move to, to the position of the next waypoint
                 Vector3 nextWaypointPosition = patrolPath.transform.GetChild(nextWaypointIndex).position;

                 enemyMovement.SetDestination(nextWaypointPosition);

                if (Vector3.Distance(transform.position, nextWaypointPosition) <= waypointTolerance)
                {
                    nextWaypointIndex = CalculateNextWaypoint(nextWaypointIndex);
                }
                yield return new WaitForSeconds(5);
            }
        }

    int CalculateNextWaypoint(int currentWaypoint)
    {
        if(currentWaypoint == patrolPath.transform.childCount - 1)
        {
            return 0;
        }
        return currentWaypoint + 1;
    }

What do you mean by “nothing seems to work”? Is the unit not moving? Not stopping? Not waiting? Not going to the next waypoint? Add some details please.

I would be hesitant to patrol in a coroutine like that.
Imagine you just set way point #1… that’s done, you don’t need to set anything until your distance is within range. At that point, you could stop the player, and call a coroutine that waits a few seconds, then chooses the new path, even sets it… and you’re back to only checking the distance every update (or every small amount of time, whichever is good for you).

1 Like

My apologies, I had a different title before so it made sense, but i edited question, it’s regarding the enemy not stopping to wait at the points.

No worries, thank you for the clarification.

This is because you end up with an infinite loop. When the if condition is false, your code effectively becomes this:

while (patrolPath != null)
{
}

Coroutines aren’t threads. They don’t run in parallel. So once you have an infinite loop in one of them, nothing else can execute, so your units can’t move themselves closer to the destination. So you will want some sort of yield each time through the loop.

while (patrolPath != null)
{
  ...

  if (Vector3.Distance(transform.position, nextWaypointPosition) <= waypointTolerance)
  {
    nextWaypointIndex = CalculateNextWaypoint(nextWaypointIndex);
    yield return new WaitForSeconds(5);
  }
  else
  {
    yield return null;   // yield until next frame
  }
}

That would solve your infinite loop issue. As far as the units not waiting, it looks like you’re setting the unit’s destination before you delay, so the unit starts moving there. It seems like you would need to move the SetDestination call after the delay, but I’m making some assumptions since I can’t see how the unit is actually moved.

while (patrolPath != null)
{
  ...

  if (Vector3.Distance(transform.position, nextWaypointPosition) <= waypointTolerance)
  {

    // we've reached a waypoint, wait for a bit, then set the next waypoint
    yield return new WaitForSeconds(5);
    nextWaypointIndex = CalculateNextWaypoint(nextWaypointIndex);
    Vector3 nextWaypointPosition = patrolPath.transform.GetChild(nextWaypointIndex).position;
    enemyMovement.SetDestination(nextWaypointPosition);
  }
  else
  {
    yield return null;   // yield until next frame
  }
}

You will need to set the initial waypoint and destination before the while loop.