As of the 10th of May, I’ve made some more progress on my prototype. This time I’ve made made an enemy AI for the game, this was done with the use of Blackboards and Behaviour trees.
Figure 1 shows the enemy AI in-game with a patrol behaviour, this state is initiated on the start of the level and is reactivated when the enemy loses sight of the player.
Using line traces, the AI is able to find any wall it can collide with and sets a position to move to. Once it reaches it, the AI will simple turn 90 degrees left and repeat.
In Figure 2, Another behaviour is when the AI starts to chase the player, this initializes once the player comes into contact with the AI’s sight radius. Once they’ve reached the player, they’ll explode and result in a game over screen.
To start creating the AI, I needed to create special blueprint known as an AI Controller. This works similarly to the Player Controller, but is more focused on receiving inputs from the environment and game world.
“The job of the AIController is to observe the world around it and make decisions and react accordingly without explicit input from a human player.”
Using this, we are able to get the base for our AI. However we are able to make this AI a lot more intelligent with the use of a Behaviour Tree.
Creating an Advanced Asset, we are able to get our Behaviour Tree. With this, we are able to give our AI Controller some logic to follow.
“While the Behavior Tree asset is used to execute branches containing logic, to determine which branches should be executed”
Finally, we’ll need a Blackboard. This’ll contain certain variables we need to refer to in our Behaviour Tree.
Anything we want our AI to know about will have a Blackboard Key that we can reference.
Now that we have all we need, I now need to go into the AI_Enemy character I created and to set its AI Controller Class to the one I’ve just created (See Figure 6).
Inside the AI Controller, it runs our behaviour tree once the game starts (See Figure 7).
It also has an event linked to AIPerception, which is used to create a sight for our enemy that’s casted to our player.
If successfully sensed then a boolean will be activated in our Blackboard to activate a chase sequence – I’ll be able to explain this later.
Next up is the Behaviour Tree itself, as you can see there are two different branches from the selector; Patrol and Chase.
If the boolean used to detect the player mentioned earlier was false, then the left part of the tree will play. If the boolean was true then the right part of the tree will activate instead.
Each will lead to a sequence that will play certain tasks, starting from the left side, this is where the player gets given actions to do in a specific order that’s numbered (See Figure 8).
Inside both sequences, you can see that they both take the SeePlayer boolean from our Blackboard (See Figure 9).
Our first task in the left sequence starts with the enemy finding a wall, this is done using a LineTraceByChannel which starts at the enemy’s position and heads forwards in front of them by 1000 units.
Once the line hits a wall, it’ll take the vector of the hit location and use it as the enemy’s next location to move to (See Figure 10)
After the execution is finished, the next task in the sequence is played which will be a Move To. This is assigned to a vector variable from the Blackboard known as TargetLocation, this is where the location for where line hits is stored (See Figure 11).
After the enemy has moved to its location, the next and final task is to rotate 90 degrees to the left. Using a SetActorRotation, I am able to change the rotation of the enemy with a value.
The value gets the actor’s current rotation on the Z axis and divides it by 90, it then rounds it to the nearest integer and times it by 90 – this is done so we can get a perfect snap for the rotation as to avoid any inaccurate rotations.
90 is then simply taken away from the player’s z axis and thus turns them a perfect 90 degrees left once we put the value into the new rotation (See Figure 12).
Once this task is finished, the whole sequence is then repeated from the first task again until the PlayerSee boolean activates.
In our next sequence for when the PlayerSee boolean is activated, a chase sequence is initiated. The first task of this sequence is to simply get the player character’s location using our AI’s perception from earlier (See Figure 13).
Next up in the chase sequence would be a task that made the AI move to this location (See Figure 14).
This sequence will keep going until the enemy loses sight of our player, thus making the SeePlayer boolean false again.
As this was my first time trying to make AI within Unreal, I feel as if the task was a success and I was able to comprehend how to use the Blackboard and Behaviour Trees.
Although the AI is quite simple, it still may need some improving such as having to go back to it’s original location after chasing the player – this may have to be left for any extra polish I can fit into the game.
Docs.unrealengine.com. (2021) AIController. [online] Available at: https://docs.unrealengine.com/en-US/InteractiveExperiences/Framework/Controller/AIController/index.html [Accessed 16 May 2021].
Docs.unrealengine.com. (2021) Behavior Tree Quick Start Guide. [online] Available at: https://docs.unrealengine.com/en-US/InteractiveExperiences/ArtificialIntelligence/BehaviorTrees/BehaviorTreeQuickStart/index.html [Accessed 16 May 2021].
Docs.unrealengine.com. (2021) Behavior Trees. [online] Available at: https://docs.unrealengine.com/en-US/InteractiveExperiences/ArtificialIntelligence/BehaviorTrees/index.html [Accessed 16 May 2021].