In this tutorial I’m going to show you how to create a basic Patrol AI. This post may seem long, however when you complete all the steps and you have a working AI you will know exactly what you did and why it’s working! Let’s get started then.
For this tutorial I used the Third Person C++ Template with no starter content.
Analyzing what we need
There are various ways you can create a basic AI in Unreal Engine. However, if you want to get the most out of the engine, you can (and probably should) use Behavior Trees. So, let’s explain what this is.
I will provide a brief explanation of what Behavior Trees are, however you should definitely check out the official documentation.
Think of Behavior Trees as Blueprints that contain AI logic. The difference between them is that Behavior Trees are far more flexible and they do not have a high cost in terms of performance. They are event-driven so they don’t constantly spam your machine with their workload in each frame. These events can trigger changes to the behavior of the AI. Here is an image of a Behavior Tree:
All trees have a root. It’s the node that contains no logic and it’s only used when the behavior tree starts or loops in order to determine what logic should they run at the current state. After every root you will see at least one composite node (in this case a Sequence – I will explain later what this is) which is usually called the real root of the tree.
The Sequence node, means that all the children (meaning all the nodes after which are connected to the Sequence node) are going to execute (from left to right) until one of them fails.
In the above image, after the Sequence, you can see the three children, which in this case are called Tasks. Tasks “do things” meaning they contain some of the logic of the AI. Note the numbers on each node on the upper left corner. Those numbers indicate the sequence that each node is going to be called. In this case, the first node that is going to get called is the “Next Target Selection”, then the “Move To”, leaving as last node the “Wait” Task.
Each behavior tree must be accompanied with at least one Blackboard. A Blackboard is a component that stores values for each behavior tree that is associated with. This meas that instead of declaring possible variables in the AI character of controller, we can extend all this functionality here. Blackboard is used only for storing information which are used by the Behavior Tree in order to determine the logic of our AI.
The information can be really anything you want, from primitive types to custom objects. The image below provides the blackboard we’re going to use for this tutorial:
The Keys of the Blackboard are the information that the Blackboard can use.
Nav mesh – which stands for navigation mesh – is a structure which contains information about the path that AI characters are able to follow. Nav mesh contains information such as areas that the AI may or may not access.
4)Character and Controllers
The last thing we need to create a basic AI is at least one Controller and one Character. A Controller is used in order to control the characters that are tied to this controller.
To sum up, for this tutorial, we’re going to use one Behavior Tree which contains the logic that the Controller will later pass down to the characters which are tied to it. The logic is going to be determined by the information provided by the Blackboard.
Setting up the AI Project
After explaining all this stuff, we’re ready to create our patrol system. The end result should be a character which will choose random points every X seconds (we will specify the X variable in seconds) that we are going to set in our map. Once a point is chosen, the character will move to the point’s location.
Create a Third Person C++ template and create the following C++ classes:
- A character, named AICharacter, which inherits the Character class
- A controller, named MyAIController, which inherits the AIController class
- A target point, named BotTargetPoint, which inherits the TargetPoint class which can be seen below:
After doing that, create:
- A Blueprint named BP_AIChar, based on the AICharacter class
- A Blueprint named BP_MyAIController, based on the MyAIController class
- A Blueprint named BP_BotTargetPoint, based on the BotTargetPoint class
- A Blackboard asset named MyBlackboard*
- A Behavior Tree named MyBT*
*In order to find the Blackboard and the Behavior Tree, right click in the empty space on your content browser and select the category Artificial Intelligence which is to the far bottom of the menu (you might have to scroll a bit).
The last thing we need, is a nav mesh. To add a nav mesh in your map from your modes tab, search for a Nav Mesh Bounds Volume and place it in your map. After adding your nav mesh, make sure you scale it so it can contain the whole starter map. If you now press the “P” keybind, you will see a result similar to the image below:
The space which is marked as green is accessible.
Setting up the AI Character
To set up our AI Character in this case, open the corresponding header file and add the following property:
class UBehaviorTree* BehaviorTree;
Compile and save your code. Then, go to the BP_AIChar and adjust the following options:
Now, we have set up the Behavior Tree and the Controller for this character.
After doing the above step, select the mesh from your Blueprint and adjust the following options as well*:
*You may need to rotate and place the mesh so it’s on the ground and it’s facing the “aqua” arrow.
After doing all the steps above, we’re done with the character once and for all! (for this tutorial at least!)
Setting up the AI Controller
The AI Controller is going to “speak” with the Blackboard as well as the Behavior Tree and give commands to all the characters that are tied to him. Open up the header file of your controller and add the following properties and functions:
After you’re done with that, switch to your source file and add the following includes:
When you’re done with the above libraries, implement the following constructor and the possess functions:
So far, we have provided the basic logic for the controller, however we still need to add the LocationToGo key in our Blackboard, otherwise we will run into problems.
Setting up the Blackboard
To set up the Blackboard, just open it up and add a new Object key and name it LocationToGo. Be aware, that it’s name is case sensitive, so if you copy and pasted the code above you need to provide the exact name seen in the image below:
Creating a custom Task for the Behavior Tree
Having done all of the above, at this point we need is to setup the logic for our Behavior Tree. However, we’re going to create our own custom Task so we can tell the Behavior Tree to choose the next location for our AI character. To do so, add a new C++ class from Editor which inherits from the BTTaskNode as the following image suggests (I named my class BTTargetPointSelection):
In case the editor throws you a link error, you’re likely missing a dependency.
In the header file of the class you’ve just added, override the following function:
virtual EBTNodeResult::Type ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) override;
This function contains the logic for the current Task we’ve just created. This means that each time this Task is going to fire, the implementation of this function will run.
Switch to your source file and add the following libraries:
When you’re done with that, type in the following code:
Now, we’re ready to create our Behavior Tree. To create nodes, right click on your Editor inside the empty space of your Tree and type in the name for each node you want to add. If you want to add the BTTargetPointSelection for example just type it, since this class inherits from the BTTaskNode it’s automatically exposed in the Behavior Tree. Open your Tree and create the following nodes:
But wait, how the Move To task knows how to choose the LocationToGo as it’s value so it can move the AI? Well, the answer is that this node will pickup the first suitable value from the Blackboard provided in the specific Behavior Tree. If you want to edit it, you can select the node and from the Details panel in your right you can change it.
Populating the map with possible Points
We now all the logic for our AI. The last thing we need is to populate our map with possible points. To do that, just drag and drop many instance of BP_BotTargetPoint in your map. Then, place one or more BP_AIChar instances and click simulate. Your bots should now be moving!
In case the bots don’t move – make sure you:
- Have placed a Nav Mesh
- Tied your Character to the AI Controller
- Typed the Blackboard Key in the correct manner.