Day 66 — Modular Waypoint System in Unity

Connor Fullarton
4 min readMay 20, 2021

--

Hey and welcome!

As you can see from the above I’ve got three guards in the game and I want to make them patrol around a fixed path. In order to do that we’ll need to set up some AI for the guards by using a modular waypoint system.

Let’s get things rolling here by creating a GuardAI script and then add a Nav Mesh Agent component to all of those guards. As a little tip you can hold shift and select all the guards in order to add the component to all three of them at the same time.

Be sure to make adjustments to the Mesh Agent if it doesn’t map well around the guards initially. You can add the GuardAI script to these three guards as well while you’re at it.

Now create an empty object called Waypoints and then create three empty objects in that called PointA, PointB and PointC and then position the points and the guard as follows:

If you need help visualising where the points go you can create three cube objects instead and uncheck the mesh renderer. Also make sure that PointA shares the same position as the guard.

Our goal here to start out with is to make the guard move from PointA to PointB and then to PointC and we can do that with this code in the GuardAI script:

public List<Transform> wayPoints;
private int _currentTarget;
private NavMeshAgent _agent;
void Start()
{
_agent = GetComponent<NavMeshAgent>();
}void Update()
{
if (wayPoints.Count > 0 && wayPoints[_currentTarget] != null)
{
_agent.SetDestination(wayPoints[_currentTarget].position);
float distance = Vector3.Distance(transform.position, wayPoints[_currentTarget].position);
if (distance < 1.0f)
{
_currentTarget++;
}
}
}

First things first make sure that in your dependencies you have using UnityEngine.AI since we’re using the nav mesh agent again.

Onto the code itself you’ll see our first instance of using a List. A list functions much the same way as an Array except that it can change dynamically at runtime. We’re going to use this to store our points we made earlier.

In our Update() we have an if statement that runs if the points stored in wayPoints is greater than 0 and if the list contains data which is what wayPoints[_currentTarget] != null is for.

Then inside the statement we’re going to each point in order by using SetDestination() again and then incrementing _currentTarget.

In short we start at wayPoints[0], then move to wayPoints[1] followed by wayPoints[2]

Once the guard reaches the last point he’ll stop and the game we’ll throw up an error, this is because it will try to access data in our list that doesn’t exist.

To sort this we need to implement some reverse functionality for the guard so he goes back down the list of waypoints. Let’s go ahead and update our code:

private bool _reverse = false;void Update()
{
if (wayPoints.Count > 0 && wayPoints[_currentTarget] != null)
{
_agent.SetDestination(wayPoints[_currentTarget].position);
float distance = Vector3.Distance(transform.position, wayPoints[_currentTarget].position);
if (distance < 1.0f)
{
if (_reverse == true)
{
_currentTarget--;
if (_currentTarget == 0)
{
_reverse = false;
_currentTarget = 0;
}
}
else
{
_currentTarget++;
if (_currentTarget == wayPoints.Count)
{
_reverse = true;
_currentTarget--;
}
}
}
}

The main difference in the code here is our new variable _reverse. This is what we’re using to let our code know whether it should move up the list or back down it.

You can see that in action in the new if/else statements that we’ve added here, if _reverse is true then _currentTarget gets reduced by 1 each time this code runs until it reaches 0 which makes _reverse fasle.

Then when it’s false it runs the code we’re used to until _currentTarget equals the number of points.

With that done correctly you’ll have something similar to the above and have your hands on a successful waypoint system! Now it’s ready for you to use the knowledge you’ve learned before to add in a walking animation to the guard.

That’s everything from me for now though.

--

--

Connor Fullarton

Hey and welcome! My name is Connor and my goal here is to put out a daily post for a full year about my game development journey.