Building A Stealth Game — Creating Waypoints For Your AI Guards

Joshua Nielsen
6 min readFeb 26, 2022

--

How to make your game’s guards move along a preset path

Photo by Catarina Sousa from Pexels

In this article we continue working on our simple stealth game in Unity. A “stealth game” is a game where we seek to achieve our objectives by avoiding contact with the enemies rather than fight them.

This particular game will be a variation on “The Great Fleece” project from GameDevHQ. This project is a collection of assets put together with the express purpose of being the aid for learning cinematography and building a basic stealth game.

In the last article, we learned how to use Unity’s navigation features to allow the player to move around by using the mouse. This time, we’re going to look at how to use those same features to have our AI enemies “patrol” along a route that we determine beforehand.

Setting up the environment and the enemy

To get started, we need to do many of the things we did to set things up for the player in the last article. First of all, we need a baked nav mesh for our guard to patrol. Check out my previous article for more information.

Next we need a game object to act as our enemy guard. Bells and whistles such as models, animations, audio, etc can all be added later. For right now, any simple object will do.

To this object we need to add a Nav Mesh Agent and a new script for our AI guard. I will name my example script SimpleAI.

Setting up the waypoints

Next we want to set up our waypoints. What we’re looking for is a collection of Vector3s that represent the position we want our guard to walk to.

We could methodically find the numbers we’re looking for and then hard code them all into our script, but there’s a better way.

What we actually want to do is make a series of empty game objects in the Unity Editor that are placed at the points we want our guard to patrol.

Here is a simple four waypoint example made with cubes. We won’t need the cube meshes though.

Be sure to organize these in a way that makes sense to you. In a real game development scenario, you would probably have many sets of waypoints for different guard paths.

Setting up the script

Now in our SimpleAI script we need to do some work. For starters, much like with our player in the last article, we need our script to have access to the Nav Mesh Agent. Create a serialized field for the Nav Mesh Agent, then assign that variable in the Unity Editor.

Next we need a variable to hold our waypoints. Create a new serialized variable in the script. This time we want a List of Transforms. Within the Unity Editor, we can now dynamically modify the size of the list and add new data points.

The Waypoints variable is an example of a serialized List

We want to change the size of the waypoints list to four to match the number of waypoint objects we’ve created. Once this is done, the Unity Editor updates to show us the list elements that we can now populate with data. Using the Unity Editor, assign to these variables the waypoints that we already created.

Making the guard move

Back in the script, the first thing we’ll need is to create a new script level integer variable to represent which waypoint in our list we are currently targeting.

Then, in our Start method, we want to make sure this new variable is set to what we want the first waypoint to be. By default the variable would be zero, and thus the first element of the list, but it does not need to be. We could also make this variable serialized if we wish, but let’s keep things simple for now and just make sure that the variable is set to zero.

Also in the Start method, we need to get our guard moving by setting a destination for the Nav Mesh Agent. As described in the previous article on player movement, for this we use the SetDestination method of the Nav Mesh Agent.

As the input for this method, we will use our list of waypoints. We will use our current target variable to access a specific waypoint in the list, which will give us a Transform value. We can then access the position property of that value to get a Vector3 value which we will use as the SetDestination method’s parameter.

This will get our guard moving to their first destination.

Keeping them moving

Next we need to modify the Update method to have the guard continue moving along the waypoints. To do this, we need to understand a couple of things. The first thing is that we need to be watching for when our guard has reached their destination. The second thing is that your guards or other objects using a Nav Mesh Agent will probably never be exactly at their destination.

I mention these two things to explain that the first thing we want in our Update method is to determine and record how far the guard object is from its destination. We can do this by using the Vector3 static method Distance. This method takes two Vector3 parameters and returns the straight line distance between them as a float variable.

Our two parameters should be the position properties of the guard object’s transform and the current target waypoint transform.

With the distance value we get from that method, we now want to compare that value to some set value. I can’t really give you a precise number for this part… It requires some trial and error.

What we’re looking for is some small value that gets our guard close enough to the waypoints, but not have such an expectation of precision that the guard stalls. That is what can happen if the value is too small.

So ultimately we want to determine when the distance to the next waypoint is less than this static value that we have determined. When it is, that is when we need to move on to the next waypoint.

Doing that is extremely simple. All we need to do is alter the value of our current target variable and then set the destination of the Nav Mesh Agent again. Since the current target variable is an integer, we can just increment through all the values and then reset to zero once the value has surpassed the size of the waypoint list.

Putting it all together, we get an Update method something like this:

float distance = Vector3.Distance(transform.position, waypoints[currentTarget].position);

if (distance < closeEnoughValue) {

currentTarget++;

if (currentTarget ≥ waypoints.Count) currentTarget = 0;

navMeshAgent.SetDestination(waypoints[currentTarget].position);

}

This will cause our guard object to continually patrol through the waypoints sequentially.

Conclusion

So we see again that the Unity navigation features save us a lot of work. Making an AI move around is pretty easy making use of those features.

This is a simple example, of course, but it wouldn’t be too difficult to make this more complex by adding branching waypoints, spots where the guard stops and looks around, or other variations on a patrol route.

In the next article, we’re going to continue working on our guard by giving them a very simple way to detect the player. Until then, thanks for reading.

--

--