I’ve been following EPIC’s Behaviour Tree Quick Start guide and delved into the fascinating world of Blackboards and Behaviour Trees (regardless of the missing u). I thought this way of implementing random walk actions in background characters would come in handy for making the game world come alive. In their example, the behaviour tree is more complex, so here’s my abbreviated (and simpler) version.
I’ll describe how we can make an AI controlled character pick a random point and walk to it, using a Behaviour Tree and a custom Task Node. There’s quite a bit of setup to make this work, but it’ll grow on you. Here’s what we need:
- a Character (I’m using a copy of the Third Person character)
- an AI Controller (plugged in to the above character)
- a Nav Mesh Bounds Volume (so the character can travel in it)
- a Blackboard
- a Behaviour Tree
- a Task Node
I’m assuming we already have all the components ready to go. I’ve described how to set some of them up in a previous article. In that example the AI controller was responsible for making the character run towards us. We’ll give this responsibility over to the Behaviour Tree now, but I won’t go into the details of setting one up here. EPIC did a fine job in this article though.
The Behaviour Tree
In my example, all I want my characters to do is walk around from one random location to the next, wait in between, and turn towards the new location before starting their journey. To add a bit of life to the whole thing, I wanted to randomise the walk speed and colour for my Unreal Guys.
My Behaviour Tree for this setup looks like this. All I have is a set of sequences that is executed one after another. At the end we wait, then start the tree again.
My corresponding Blackboard has a single Vector key called PatrolLocation. We’ll use this value to pass it between tasks and Actors. This will hold the “go-to” location.
Finding a new random location
The secret sauce to pick that new location is indeed a node called GetRandomReachablePointInRadius. Here’s how we can use it in context. This goes into a custom Task Node called BTT_FindNewLocation:
Our first event (Receive Execute AI) is called when this task is first executed by the Behaviour Tree. It’s like Event Begin Play for Actor Blueprints. From here I’ll grab a reference to my controlled character by way of a cast node. If it fails, we’ll finish the execution without success and exit this task.
When successful, things get a little complicated. We’ll get our character’s Actor Location and add its return value into a that amazing GetRanomReachablePointInRadius node. We need to provide a radius in pixels (between 1000 and 5000 works quite well). I’ll promote this to a public variable so we have access from the behaviour tree. What makes this node so exciting that it will check the Nav Mesh Volume and return a location that our controlled character can actually reach. Anything unreachable won’t be returned. Neat!
This node might fail for various reasons though (no nav mesh, no character location, radius too small etc) so it has a boolean return value, delivering if it was successful with its complex calculation. We’ll use this to plug into a Branch Node. On both success and failure we’ll add a Set Blackboard Value as Vector node and Finish Execute successfully, exiting this task. Hence we’ll definitely give our Blackboard a vector on return.
The difference is that on success, we’ll deliver the new random location. On failure, we’ll return the character’s current location. Note the key pin on those two nodes: it’s a type of Blackboard Key. This is technically a string must match the entry we want to reference in the Blackboard, hence it’s set to the same as defined as Vector above (it’s case sensitive I believe).
By the end of this task, our Behaviour Tree will have a new value in PatrolLocation.
Rotating towards the new location
The next task in the list will take this new location and rotate our character around. I’ve added this as a custom event on my character rather than a new task, because there appears to be no way to use a Timeline inside a Task Node. This is just a bit of eye candy really, turning our character around. I’ve explained how this works here.
Randomising our Walk Speed
Our next task in the tree is to wait a relish the new rotation for a bit (i.e. wait), then give our character a new walk speed. I’ve implemented that as a function in my character.
I’ll start by grabbing a reference to the Character Movement, then I set the Max Walk Speed on it. To make it random, I’m using a Random Float in Range node. See what values work best for your project. Lower values make the feet of your characters slide a bit. Faster values make them look as if they’re too much in a hurry.
To call this custom function from the Behaviour Tree, I had to create a new Task Node (called BTT_RandomiseWalkSpeed). All it does is grab a reference to my character, call the function and mark the task as successfully finished.
Moving towards the new location
The Behaviour Tree as a built-in Move To task. We can use that to make our controlled character move. All we need to provide is the new location. Thankfully we have a reference to such a vector in our PatrolLocation key! Let’s select it on the right hand side and bind those values together.
Using the Behaviour Tree on our AI Controller
To make our AI Controller obey that Behaviour Tree, we need to bind the two together. Much like the Begin Play event, an AI Controller has an On Posses event. We’ll use that to plug in our Behaviour Tree (select it under BTAsset; mine is called BT_Enemy)
I believe that’s all there’s to it. With one or several or our AI characters placed in the game world, they should all start walking at random speeds to random points, linger for a bit, turn around and walk towards another location.