AI is a decision-making process that adds NPCs in a game. AI is a programmable decision-making process for NPCs to govern their responses and behaviors in a game. A game character that is not controlled by a human player has no form of intelligence, and when these characters need to have a higher form of decision-making process, we apply AI to them.
AI in games has progressed tremendously over the years and NPCs can be programmed to behave in a certain way, sometimes, with some form of randomness, making it almost unpredictable so that players do not have a simple, straightforward strategy to win the level.
The decision-making process, which is also the logic of the NPCs, is stored in a data structure known as a Behavior Tree. We will first learn how to design a simple Behavior Tree then learn how to implement this in Unreal Engine 4.
Learning how to design a good decision-making tree is very important. This is the foundation on which programmers or scripters rely to create the behavior of a character in a game. The Behavior Tree is the equivalent of a construction blueprint for architects who design your house.
A Behavior Tree has roots that branch out into layers of child nodes, which are ordered from left to right (this means that you always start from the left-most node when traversing the child nodes) that describe the decision-making process. The nodes that make up the Behavior Tree mainly fall into three categories: Composite, Decorator, or Leaf. Once you are familiar with a couple of the common types of nodes in each of the three categories, you would be ready to create your own complex behaviors:
Composite |
Decorator |
Leaf | |
---|---|---|---|
Children nodes |
Having one or more children are possible. |
This can only have a single child node. |
This cannot have any children at all. |
Function |
Children nodes are processed, depending on the particular type of composite node. |
This either transforms results from a child node's status, terminates the child, or repeats the processing of the child, depending on the particular type of Decorator. |
This executes specific game actions/tasks or tests. |
Node examples |
The Sequence node processes the children nodes from the left-most child in sequence, collects results from each child, and passes the overall success or failure result over to the parent (note that even when only one child fails and the rest succeed, the overall result is failure). This can be thought of as an AND node. |
The Inverter node converts a success to a failure and pass this inverted result back to the parent. It works vice versa as well. |
The Shoot Once leaf node shows that the NPC would shoot once and return a success or failure, depending on the result. |
This is a simple walkthrough of how a Behavior Tree can be constructed. The following legend will help you identify the different components of a Behavior Tree:
The following figure shows a simple response for an enemy NPC. The enemy will only start attacking when the war starts.
The following figure has been expanded on the earlier Behavior Tree. It gives a more detailed description of how the enemy NPC should approach the target. The NPC will run towards the target (the player character in this case), and if it is close enough, it starts shooting the player.
Next, we set more behaviors that show how the NPC will shoot the player. We give the enemy NPC a little intelligence: hide if someone is shooting at it and start shooting if no one is shooting at it; if the player starts moving in toward it, the NPC starts moving backward to a better spot or goes for a death match (it shoots the player at close range).
The Unreal Editor allows complex Behavior Trees to be designed using the visual scripting Blueprints together with several AI components.
There is also an option in Unreal Engine 4 where very complex AI behaviors can be programmed in the conventional way or in combination with Blueprint visual scripting.
The nodes for BT in UE4 are broadly divided into five categories. Just to recap, we have already learned a little about the first four in the previous section; Service is the only new category here:
For AI characters to move around in the game level, we need to specifically tell the AI character which areas in the map are accessible.
Unreal Engine has implemented a mesh-like component known as Navigation Mesh. The Navigation Mesh is pretty much like a block volume; you could scale the size of the mesh to cover a specific area in the game level that an AI character can move around in. This limits the area in which an AI can go and makes the movement of the character more predictable.
Go to Modes | Volumes. Click and drop Nav Mesh Bounds Volume into your game level. The following screenshot shows where you can find Nav Mesh Bounds Volume in the editor:
If you are unable to see Nav Mesh Bounds Volume in your map, go to the Show settings within the editor, as shown in the following screenshot. Make sure the checkbox next to Navigation is checked:
Scale and move the Navigation Mesh to cover the area of the floor you want the AI character to be able to access. What I have done in the following screenshot is to scale the mesh to fit the floor area which I want my AI character to walk in. Translate the mesh upward and downward to allow it to be slightly above the actual ground mesh. The Navigation Mesh should sort of enclose the ground mesh. This screenshot shows how the mesh looks when it is visible:
Here's an overview of the components that we will create for this tutorial:
The important takeaway from this tutorial is to learn how the components are linked up to work together to create logic; we make use of this logic to control the behavior of the NPC.
In terms of file structure in Content Browser for these different file types, you can group the different components into different folders. For this example, since we are only creating one NPC character with logic, I will put all these components into a single folder for simplicity. I created MyFolder
under the main directory for this purpose.
We start creating the AI logic of our NPC starting with AIController and Character. The Character Blueprint is the object that contains the link to the mesh, and we will drag and drop this Character Blueprint into the level map after we make some initial configurations. The AIController is the component that gives the NPC character its logic.
We will discuss the rest of the other three components as we go along.
Go to Create | Blueprint. Type in AIController
into the textbox to filter by class, as shown in the following screenshot. Select AIController as the parent class.
Rename this AIController Blueprint as MyNPC_AIController
:
We will come back to configure this later.
Go to Create | Blueprint, and type in Character
in the textbox to filter by class. Select Character as the parent class for the Blueprint, as shown in the following screenshot. Rename this Blueprint as MyNPC_Character
.
Double-click on MyNPC_Character in Content Browser to open the Character Blueprint editor. Go to the Components tab.
In the Perspective space view, you will see an empty wireframe-capsule-shaped object, as shown in the following screenshot. In the Details panel in the Blueprint editor, scroll to the Mesh section, and we will add a mesh to this Blueprint by selecting an existing mesh we have. You can go to Content Browser, select HeroTPP, and click on the arrow next to it. Alternatively, you can click on the search button next to the box and find HeroTPP:
After selecting HeroTPP as the skeletal mesh, you will see the mesh appearing in the wireframe capsule. Notice that the HeroTPP skeletal mesh is much larger than the capsule wireframe, as shown in the following screenshot. We want to be able to adjust the size of the wireframe to surround the height and width of the skeletal mesh as closely as possible. This will define the collision volume of the character.
This figure shows when the wireframe for the skeletal mesh is the correct height:
Go to the Default tab of MyNPC_Character, scroll to the AI section, and click on the scroll box to display the options available for AIControllers. Select MyNPC_AIController to assign the character to use this AIController, as shown in this screenshot. Compile, save, and close MyNPC_Character for now.
Go to Content Browser, and click and drop MyNPC_Character into the level map. Compile and play the level. You will see that the character appears in the level but it is static.
Similar to the early implementation of assigning an animation to the mesh, we will add animation to MyNPC_Character. Double-click on MyNPC_Character to open the editor. Go the Default tab, scroll to the Animation section, and assign the Animation Blueprint (MyNPC_Blueprint), which we created earlier for this Character Blueprint. The following screenshot shows how we can assign animation to the character. Compile and save MyNPC_Character:
Now, play the level again, and you will see that the character is now walking on the spot (as we have set the speed to 100 in the Animation Blueprint, MyNPC_Blueprint).
Go to Content Browser. Then, go to MyFolder and double-click on MyNPC_AIController to open the editor. We will now add nodes in EventGraph to design the logic.
Our first mission is to get the character to move forward (instead of just walking on the same spot).
The following are the nodes to be added in EventGraph:
The following screenshot shows the final EventGraph that we want to create:
Now, play the level again, and you will see that the character is now walking forward. But it's doing this a little too quickly. We want to adjust the maximum speed at which the character moves.
Double-click on MyNPC_Character to open the editor. Go to the Default tab, scroll to the Character Movement section, and set Max Walk Speed to 100, as shown in this screenshot:
BlackBoardData functions as the memory unit of the brain of the NPC. This is where you store and retrieve data that would be used to control the behavior of the NPC. Go to Content Browser, and navigate to Create | Miscellaneous | Blackboard. Rename it MyNPC_Brain
.
Behavior Tree is the logic path that NPC goes through to determine what course of action to take.
To create a Behavior Tree in Unreal Engine, go to Content Browser | Create | Miscellaneous, and then click on Behavior Tree. Rename it MyNPC_BT
.
Double-click on MyNPC_BT to open the Behavior Tree editor. The following screenshot shows the setting that we want for MyNPC_BT. It should have MyNPC_Brain set as the BlackBoard asset. If it doesn't, search for MyNPC_Brain and assign it as the BlackBoard asset.
If you have already gone through the earlier exercise and are familiar with a Behavior Tree, you will notice that in this editor that there is a Root node, which you could use to start building out your NPC's behavior.
The next step here is to add on a composite node (either Sequence, Selector, or Simple Parallel). In this example, we will select and use a Sequence node to extend our Behavior Tree here. You can click and drag from the Root node to open up the contextual menu, as shown in the following screenshot. Alternatively, just right-click to open up the menu and select the node that you want to create.
We will add a Wait task from the Sequence node. Click and drag to create a new connection from the Sequence node. From the contextual menu, select Wait. Set Wait to be 15.0s, as shown in this screenshot. Save and compile MyNPC_BT.
After compiling, click on Play in the Behavior Tree editor. You would see the light moving through the links and especially from the Sequence node to the Wait task for 15s.
Now that we have a simple implementation of the Behavior Tree, we want our NPC character to start using it. How do we do this? Go to Content Browser | MyFolder, and double-click on MyNPC_AIController to open up the editor. Go to the EventGraph tab where we initially created a simple move forward implementation. Break the initial links between the IsValid node and Add Movement Input. Rewire them based on the following screenshot by linking the IsValid node to a new Run Behavior Tree node. In the Run Behavior Tree node, assign BTAsset to MyNPC_BT. Next, replace Event Tick with Event Begin Play (since the BT will now replace the thinking function here). Save and compile.
We want to now make the NPC select a location on the map and walk toward it.
This requires the creation of a custom task where the NPC has to select a target location. We have already created an entry in the BlackBoardData to store a vector value. However, we have not made a way to assign values to the data yet. This would be done by creating a custom Behavior Tree task.
Go to Content Browser | Create | Blueprint. For the parent class, search for BTNode and select BTTask_BlueprintBase, as shown in the following screenshot. Rename this task as Task_PickTargetLocation
.
Double-click on the newly created Task_PickTargetLocation. Go to EventGraph, create the following nodes, and link these nodes:
Notice that there is a
New Target Loc variable linked to Key of Set Blackboard Value as Vector. We need to create a new variable for this. Click on +Variable, as shown in the following screenshot, to create a new variable. Name the new variable New Target Loc
.
Click on the newly created New Target Loc to display the details of the variable. Select BlackBoardKeySelector as the variable type, as shown in this screenshot:
Add a new link from the current Sequence composite node. Place the Task_PickTargetLocation node to the left of the Sequence node so that it would be executed first, as shown in the following screenshot. Make sure that New Target Loc is set as TargetLocation:
Delete the Wait node, and add the Move To node in its place. Make sure that Blackboard Key for Move To is set as TargetLocation, as show in this screenshot:
After compiling, click on Play to run the game. Double-click on MyNPC_BT to open the Behavior Tree editor. You would see the light moving through the links and the TargetLocation value changing in the Blackboard, as shown in this screenshot:
Remember to go back to the map level and see how the NPC is behaving now. The NPC now selects a target location and then move to the target location. Then, it selects a new target location and moves to another spot.
With this example, you have gained a detailed understanding of how to set up AI behavior and getting AI to work in your level. Challenge yourself to create more complex behaviors using the knowledge gained in this section.
I am sure you have noticed that we definitely need to create more complex behaviors to make a game interesting. In terms of implementation, it is often easier to implement more complex AI through a combination of programming and use the editor functions to take this a step further. So, it is important to know how AI can be triggered via the editor and how you can customize AI for your game.