skip to Main Content

Creating a basic Patrol AI

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

1)Behavior Trees

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:

bt

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.

2)Blackboard

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:

blackboard

The Keys of the Blackboard are the information that the Blackboard can use.

3)Nav mesh

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:

  1. A character, named AICharacter, which inherits the Character class
  2. A controller, named MyAIController, which inherits the AIController class
  3. A target point, named BotTargetPoint, which inherits the TargetPoint class which can be seen below:

WayPointClass

After doing that, create:

  1. A Blueprint named BP_AIChar, based on the AICharacter class
  2. A Blueprint named BP_MyAIController, based on the MyAIController class
  3. A Blueprint named BP_BotTargetPoint, based on the BotTargetPoint class
  4. A Blackboard asset named MyBlackboard*
  5. 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:

navmesh

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:

UPROPERTY(EditAnywhere,Category=”AI”)
class UBehaviorTree* BehaviorTree;

Compile and save your code. Then, go to the BP_AIChar and adjust the following options:

bp_aichar

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*:

bp_aichar1

*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:

#include “AICharacter.h”
#include “BotTargetPoint.h”
#include “BehaviorTree/BlackboardComponent.h”
#include “BehaviorTree/BehaviorTreeComponent.h”
#include “BehaviorTree/BehaviorTree.h”

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:

blackboard

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):

bttasknode

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:

#include “BotTargetPoint.h”
#include “MyAIController.h”
#include “BehaviorTree/BlackboardComponent.h”

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:

bt1

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.

 

This Post Has 42 Comments

    1. Every sub editor of the engine is essentially c++/c code so I’m assuming that this is possible. Since the purpose of the behavior tree is to provide a visual aspect of the AI state and logic at any time I wouldn’t recommend going in such a low level, but that’s just my personal opinion!

      -Orfeas

      1. I just think that ,if I make a big and complex behavior tree,the Blueprint version will slower than the c++ on the runtime . In addition ,I prefer to make my project by c++ only,I like unified style on programming

        1. Blueprints are not that far from C++ in terms of performance (considering tha BPs are a based on the latter one). Moreover from 4.11 version and later on, Unreal has the functionality to cook your Blueprints into C++ code so you won’t have to worry about performance issues.
          It’s true that complex Blueprints result in spaghetti code (which I totally hate) but I don’t think that you will encounter this issue in BTs.

          -Orfeas

  1. Hi Orfeas, I get a “member function declared with ‘override’ does not override a base class member” at the header file for BTTargetPointSelection. Know how to fix it?

    1. This means that you’re attemping to override something that doesn’t exist. Make sure that you inherit the right class and the signature of your ExecuteTask function is the following:

      virtual EBTNodeResult::Type ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) override;

      -Orfeas

      1. Aha one of my plugins interfered with Unreal when I was making the BTTargetPointSelection resulting in it not inheriting properly from BTTaskNode.

        I deleted the offending class and made a new one and all is working fine now.

  2. Hi Orfeas, thank you for your great tutorials. I am following your tutorial in 4.11. I did everything like in tutorial, but my bots don’t move. I placed a Nav Mesh, tied your Character to the AI Controller and typed the Blackboard Key in the correct manner. Everything was done correct, but i did it for 2d bot. Will this work for 2d character? I think it should work even for 2d characters.

    1. I haven’t tried creating an AI for a 2d character but I don’t see why it shouldn’t work. Does your behavior tree executes at all?

      -Orfeas

  3. Hey, even though the BT is executed and the pawnsensing works, my ai doesn’t move at all.
    I noticed that the location to go key keeps changing all the time.
    Any ideas what I’m doing wrong?

  4. Hey,

    I have done everything on the tutorial but when i go to simulate Unreal crashes every time, I’m guessing a stack overflow is happening somewhere, do you have any idea what might be causing this?

    Thanks,

    Ryan

    1. It’s more likely that you have a null reference somewhere. If you can provide your game’s callstack I might be able to point out where things go awry.

      -Orfeas

      1. Hey,

        I redone the tutorial and everything is working now you were probably right about the null reference, I have done this tutorial and the AI Follow tutorial but can’t seem to get the AI to do both I have to set the behavior tree so he either follows me or wanders around, is there anything you can suggest?

        Thanks,

        Ryan

        1. Debug your Behavior Tree and take a step back to examine your code once again to determine what’s going wrong.

          -Orfeas

  5. Hi Orfeas:

    Thank you for the tutorial! When you says “Open up the header file of your controller and add the following properties and functions:”, should there be some codes after it? I didn’t see any properties or functions following it.

    Thanks,
    wcl

    1. Hello,

      This is normal. Most classes have no generated code besides the UCLASS macro and its header files by default. The controller class is one of them.

      -Orfeas

      1. No, I mean in the blog when you says “Open up the header file of your controller and add the following properties and functions:”, what properties and functions are you referring to? I can’t see any codes for them in your article. Maybe you forgot to type the code there?

        Thank you for your patience,

        wcl

          1. Problem sovled!I think Chinese government for some reason blocked this website. Now I can see your code using a VPN.

            Appreciate your patience,

            Chenglin

  6. How would I have an AI attack my player repeatedly if the player is inside a certain range?

    I tried to do it in C++ but the most I could accomplish was having the AI run to the player and then attack him once.
    I think it has something to do with the FinishLatentTask() function but i’m not sure.

      1. I was actually able to get the distance check working in C++ but the launch attack function is still not working no idea why.

        1. Finally got it working, this was the main line I was missing

          if (AttackMontage && !Animation->Montage_IsPlaying(AttackMontage))
          {
          GLog->Log(“Playing attack montage”);
          PlayAnimMontage(AttackMontage);
          }

          Now I just need to figure out why my distance check function only worked when I added this function
          FinishLatentTask(OwnerComp, EBTNodeResult::Succeeded);

          1. I bother with the FinishLatentTask(OwnerComp, EBTNodeResult::Succeeded) too,Do you figure it out how this function work?

  7. Hi Orfeas, thanks for your great tutorial, this helped me tremendously. One minor change i had to make to get it working in UE 4.15: i had to make sure that the base class of LocationToGo in the Blackboard is set to Actor, not Object. Otherwise it wouldn’t show up as a valid target parameter within the “MoveTo” Task.
    Cheers! ponx

  8. Thank you so much for this tutorial! I’ve got it working as expected, I just have a question about implementation. How would you go about doing this same thing for multiple AI characters in one level? For example, I have a level I’m making where there are 3 floors the player can navigate, and I want a separate patrolling AI on each floor. Would I need to create 3 separate sets of these (behavior tree, blackboard, character, controller, and target points) or is there a way I could reuse the one I already created?

    Really it seems like if I could just have the AI access a new array of target points for each navigation mesh I set, that would work, but I don’t know how I would go about implementing that.

    What do you think?

    1. I would add a Box Collision on each floor. You can assign each character to a placed Box Collision (via a new exposed property on your AI character which would be a reference to the placed Box Collision inside your Level) and then get all the overlaping actors from the assigned box and populate the BotTargetPoints array from there.

      -Orfeas

  9. Hey Orfeus thanks for the tutorials I am not even sure if you are still looking these up but I am having a bit of trouble. I have applied what you are doing here to my own project where I have a single C++ box as my spawned thing instead of a mannequin. other than this though I haven’t changed anything. is there anything specific I need to attach to a pawn to get it to move on a navmesh?

    1. Hello,

      This sounds like you have assigned a wrong class in your spawn actor functions.

      -Orfeas

  10. Hey Orfeus thanks for the tutorials i’ve followed it however but when i click play in the editor i crash and a error message says

    UNREAL sertion failed: (Index >= 0) & (Index < ArrayNum) [File:C:\Program Files\Epic Games\UE_4.19\Engine\Source\Runtime\Core\Public\Containers/Array.h] [Line: 610] Array index out of bounds: 0 from an array of size 0
    and wonder if u have any idea what the cause might be
    thanks.

  11. Hey sir. Great tutorial thank you. I was wondering how to get it to work with multiple AI’s. In my project I would like to have 4 AIs all patroling different parts of the map. However, they all go to the same target points currently. How would you go about making them patrol separate points without having to remake everything four times?

  12. Hey Orfeas, thanks a lot for the tutorial.
    I found that when creating the Blackboard Key I had to ensure that the Base Class was Actor or else the BT couldn’t find reference to it.
    Might be useful to update the tutorial to include this

    Thanks

Leave a Reply to Alan How Cancel reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Back To Top