Creating a Modular Waypoint System for AI in Unity

Calum Slee
Level Up Coding
Published in
3 min readAug 24, 2021

--

In our game, we have 3 guards to initially sneak past. Currently they’re stationary, let’s write up a modular script to create patrol routes.

Adding NavMeshAgent components to each of our guards, will allow them to traverse the environment much like the player through SetDestination. The difference being, that they won’t be moving off of user input.

To create “waypoints”, we can create empty GameObjects and store their Transform’s in a List. Each Guard object can now contain a different sized List with various empty Transform targets, or none at all. We use a List rather than an Array to give us the chance to dynamically update the waypoints through code later if need be.

With each Guard and their respective Waypoints set up, we can also create an Animator Tree similar to the Player’s with transitions set by a bool between Idle and Walking.

Now for the code. We first need references to both our NavMeshAgent and our Animator. Then in Update, I continuously call a method named WayPointMovement.

In this method, we first need to check if the waypoint List contains any Transforms. This prevents any errors occurring for guards that may not have waypoints yet, or are simply staying stationary.

We then have an int value, storing which number of the List we currently want to access, if this is accessing a Transform that exists, we can SetDestination to that Transform. Then we can also set the Animator walk bool to true.

To detect when the destination is reached, we can mimic our Player code with the use of Vector3.Distance

If the distance is less than 1 unit, we can stop the NavMeshAgent and then start a Coroutine to enable some idling time before selecting the next target.

In this Coroutine we can set a target reached bool to true to prevent this from being called multiple times from the code above. Next we set the Walk bool to false.

I only want my guards to idle at the first and last waypoints, therefore, we can check if either of these are the case, before waiting for a random amount of seconds. Next, we call a method to Set the Next Target.

To set the next target, we need to be able to iterate through the List in both directions, therefore, the use of a bool named reverse can be used to check and set the direction. We either increment or decrement the int value of the List depending on this bool. Then we do a check to see if we’re at the beginning or the end, and flip the bool.

Lastly, we can set the Target Reached bool to false, so as to let the distance calculation and Idle Coroutine rerun, and additionally set the is Stopped function of the NavMeshAgent to false.

--

--