Feature Highlight: Creating a Modular Waypoint System for AI Character Pathing in Unity

Chase Mitchell
5 min readMay 12, 2021

--

It’s time to bring our game to life with some animating NPCs. In this stealth game we will be implementing a few guard characters that will path around our scene with a flashlight looking for our player. If our player is caught in the light, it’s game over! Let’s set up the movement tracks.

Before we get into the code, the first step is to ensure all pathing NPCs have a NavMeshAgent component so that they can reference the walkable areas that are allowed within our mesh. I’ll be controlling all guard behavior with a C# script called GuardAI, so we then add this script to each Guard NPC as well.

Inside our script, we create a list of waypoints that our guards can path between. Using the System.Collections.Generic namespace we can reference the List attribute, which is similar to an array but allows you to dynamically change the size of the list at runtime. This is useful for our guards because they might all have a different number of waypoints associated with their movement.

This list will be of type transform because we are storing a list of positions. Now in the inspector we can set the list size on each guard independently:

Let’s create the waypoint locations for our first guard. The way I like to do this is to duplicate my character object and drag a new copy to each location I would like to save as a waypoint. By doing this you get to see a visual representation of where your character will be placed before finalizing the location.

This guard will be patrolling the first hall and then curving up along the right aisle. Once each point is finalized you can disable the 3D asset and any components and you will be left with the desired transform positions.

Once we have our points set we add them to the waypoints list component on this guard.

Now we can set up the movement. Step 1 is to get a handle to the NavMeshAgent component on our guard:

Next we need to set up a variable for our target. Because we have multiple points to select between, we use a target variable to determine which point is the next target for our movement.

Then in void Start() we assign our first point in the series. We can do this by referencing the index position of our waypoint in the list, our first point being at index position 0.

Note it is important to do two null checks here to avoid errors, because as it stands only 1 of our guards has a waypoint set up for position 0, and the other two guards have not been assigned any points. In fact, one of our guards will be stationary throughout the game and will have zero elements in its list count, so this will always cause an error if we are not null checking that we both have a count > 0 and that index position 0 is assigned. Without these null checks we will get an “Argument out of range exception” error. It’s always a best practice to do null checks whenever you are executing a command that requires an external connection to be in place in order to work properly.

This code will assign the first point to our currentTarget variable automatically when the game starts, but we still haven’t given it the command to move:

Be sure to add the UnityEngine.AI namespace to use the destination command

Now how do we dynamically update our target as we reach each waypoint along the path? We can do this by calculating the distance from the currentTarget and if we reach a small enough distance that we have effectively reached that point, we update our target to the next point. It is also beneficial at this stage to create a variable for our index position values so that we can increment them in our code:

Don’t forget to null check first!

The logic above is that as we approach a waypoint, if our index value is still smaller than our list size (meaning we have not yet reached the last point in the list) move to the next position in the index, update the currentTarget to that position, and move the character to the new waypoint. If we have reached the last point in our list (our index position value +1 matches our maximum number of items in the list) reset the index position to 0 and start again from the beginning. This will loop our pathing for the duration of the game. Note that we do index position +1 because the index starts at 0 and runs from 0 to 3 while the list count begins at quantity of 1 and runs from 1 to 4.

Now we have successfully created a modular looping waypoint system for our AI characters. It does not matter how many waypoints we have in the list, as our code is designed to increment each point one by one until we reach the end of the list, at which point we reset to the beginning. This is a scalable approach that you can use to easily implement pathing AI behavior into your games. I hope you found it helpful. In the next guide I’ll cover how to give our AI the ability to “see” — see ya there!

--

--