An enemy walks around a room and comes after the player when it spots them. Hide behind a wall and it stops chasing and starts walking again. Building an enemy like this requires thinking about "when do we switch to which behavior," on top of the movement itself.
A Behavior Tree is a system for building that choice of behavior as a tree. You express a policy such as "chase if the target is visible, otherwise patrol" through branch conditions and ordering.
In other engines: neither Unity nor Godot has a standard feature equivalent to this (you cover it with assets or your own code). The fact that it is built into the engine is an advantage when building AI in UE.
In this article we first get patrol working, then add spotting and chasing the player. At the end we display "Attack" when the enemy gets close and confirm the behavior actually switched.
What You'll Learn
- How AI Controller, Behavior Tree, and Blackboard divide the work
- How to read a tree using Selector and Sequence
- The procedure of getting patrol working first, then adding the chase branch
- How Observer Aborts switches behavior mid-action
What You'll Build
- An enemy that picks a nearby destination, walks to it, and waits 2 seconds
- It aborts patrol and gives chase when it spots the player, logging an attack when it gets close
- It aborts the chase and returns to patrol when it loses sight
This is a single-player example using UE5's Third Person template. Attack animations and damage can be added once this AI's decision-making works.
- Three roles that drive the AI
- Selector and Sequence: how to read the tree
- Task, Decorator, and Service
- Prepare the enemy and somewhere to walk
- Get patrol working first
- Remember the player on the Blackboard when spotted
- Add the chase branch and switch mid-action
- Run it and compare the tree against the values
- Summary
Three roles that drive the AI
A Behavior Tree alone does not move the enemy on screen. You combine something that controls it, something that chooses behavior, and somewhere to remember decision material.

| Part | Its role here |
|---|---|
| AI Controller | Controls the enemy's body and starts the Behavior Tree |
| Behavior Tree | Looks at conditions and picks patrol, chase, and so on |
| Blackboard | Stores "who to chase" and "where to walk" |
The controlled body is called a Pawn. The Character we use here is a kind of Pawn with movement built in. Thinking of it as "the AI Controller is the driver, the Character is the body" makes the roles easy to separate.
The Blackboard is like a shared note the AI reads. The logic that spots a target writes "who to chase," and the chase logic reads it and moves. The spotting logic no longer has to send individual instructions to patrol, chase, and everything else.
Selector and Sequence: how to read the tree
You follow the tree from the Root at the top. Children under the same parent are tried from the left. The first thing to learn is the two kinds that decide how a child's result is handled.

| Kind | When a child succeeds | When a child fails |
|---|---|---|
| Selector | Succeeds and finishes there | Tries the next child. Fails if all fail |
| Sequence | Moves to the next child. Succeeds if all succeed | Fails and finishes there |
A Selector expresses "which behavior to choose." Put "chase the player" on the left and "patrol" on the right, and as long as the chase condition holds, that one is picked first.
A Sequence expresses "what steps the chosen behavior goes through." For patrol that is "pick a destination → move there → wait a moment." If the movement fails, it does not advance to the wait; it ends this sequence as a failure.
"Running" is neither success nor failure
A part responsible for a single behavior, such as movement, is called a Task. While the enemy walks toward its destination, the movement Task is Running (In Progress). Simply issuing the move order is not success, and it does not advance to the next Task until it arrives.

The same is true of a Selector. The chase on the left being in progress does not mean the patrol on the right also starts. Waiting for one Task's result, and only advancing once success or failure is decided, is the basic behavior of this tree. Switching behavior mid-action comes later.
Task, Decorator, and Service
The parts of a tree include not only ones that act but ones that check conditions.

| Part | Role | Example |
|---|---|---|
| Task | Performs a behavior | Move To to move, Wait to wait |
| Decorator | Checks whether a branch or Task may run | Let it through if "there is a target" |
| Service | Repeatedly checks while the branch it is attached to runs | Measure the distance to the target at an interval |
Splitting it as Decorator is condition, Task is behavior makes the flow of judgment visible when you read the tree. That said, a Task may also check its target just before running and return failure if it is invalid.
A Service stops once you leave its branch. If the check is needed during every behavior, attach it to the parent that bundles both branches. Spotting and losing sight here use AI Perception notifications, covered later, so there is no need to write your own Service.
Prepare the enemy and somewhere to walk
Create the enemy's body and its controller
Open the Third Person template and create an "AI" folder to work in.
- Duplicate "BP_ThirdPersonCharacter" and name it "BP_Enemy." You get to reuse the enemy's appearance and walk animation.
- Open BP_Enemy and delete the input handling nodes in the EventGraph. The player you duplicated from stays as it is.
- Create a new "Blueprint Class," search "All Classes" for "AIController," and select it. Name it "BP_EnemyAIController."
- In BP_Enemy's "Class Defaults," set the control settings in the table below. The two Character Movement entries are set by selecting that component under "Components."
| Setting | Value |
|---|---|
| AI Controller Class | BP_EnemyAIController |
| Auto Possess AI | Placed in World or Spawned |
| Auto Possess Player | Disabled |
| Use Controller Rotation Yaw | Off |
| Character Movement → Orient Rotation to Movement | On |
| Character Movement → Max Walk Speed | 300 |
Possessing is a Controller taking over control of a Pawn. The Auto Possess AI setting attaches an AI Controller both to enemies placed in the level and to ones spawned later. The rotation settings make the enemy face the direction it walks. UE's default unit is centimeters, so Max Walk Speed 300 is 3 m/s.
Build a map the AI can walk on
Place one enemy on a flat part of the level, add a "Nav Mesh Bounds Volume," and cover the whole floor the enemy and player walk on. Press P and confirm the green area appears on the floor.
This NavMesh is the AI's "map of where it can walk." Even if it looks like a floor, Move To cannot walk there without a map. If it does not turn green, check the NavMesh article first.

Create the Blackboard and Behavior Tree
Right-click in the content browser and create a "Blackboard" and a "Behavior Tree" from "Artificial Intelligence." Name them "BB_Enemy" and "BT_Enemy."
Open BB_Enemy and create the following two entries with "New Key." A Key is the name of an entry you store.
| Key name | Type and setting | What it stores |
|---|---|---|
| TargetActor | Object, Base Class = Actor | The target being chased |
| PatrolLocation | Vector | The next place to walk |
An Object holds a reference pointing at "that specific thing in the level." It is not a field for a name string. A Vector is three values X, Y, and Z, representing a location here.
Open BT_Enemy, set "Blackboard Asset" to BB_Enemy, and save. Now the tree can select both Keys.
Get patrol working first
Create a Task that picks a destination
From BT_Enemy's "New Task," choose "BTTask_BlueprintBase" and name it "BTT_FindPatrolLocation." In the Task, create a variable "PatrolKey" of type Blackboard Key Selector and turn on "Instance Editable."
Blackboard Key Selector is the type for choosing "which Key to write to." Enabling Instance Editable lets you specify "PatrolLocation" from the details of the Task placed in the tree.
Add "Event Receive Execute AI" to the Task's EventGraph. That event is the signal "start this Task." "Controlled Pawn" hands you the enemy body being controlled.
First, pick the coordinate to write with these connections.
- Controlled Pawn → Get Actor Location's "Target." This gets the enemy's current position.
- Current position → Get Random Reachable Point in Radius's "Origin." Set "Radius" to 1000 (a 10 m radius).
- Add a "Select Vector" and connect Random Location to "A," the enemy's current position to "B," and the search's Return Value to "Pick A."

Get Random Reachable Point in Radius looks for a walkable point nearby. Return Value true means one was found, false means none was. Select Vector picks A on true and B on false, so on failure the destination becomes the current position.
Next, write the chosen coordinate and finish the Task.
- Receive Execute AI's white exec line → Set Blackboard Value as Vector → Finish Execute.
- On Set Blackboard Value as Vector, connect a Get of PatrolKey to "Key" and the Select Vector's Return Value to "Value."
- Turn on "Success" on Finish Execute.

Finish Execute is the node that reports back to the tree that the Task is done. Success here means "the destination was written," not that the enemy arrived. Movement is left to the following Move To.
Even when the search fails, moving to the current position and then entering the wait avoids immediately retrying the search over and over. Compile and save.
Build the patrol tree and start it
In BT_Enemy, drag from Root and add a Selector. Put a Sequence under it and set its "Node Name" to "Patrol." Arrange the Sequence's children from the left in this order.
BTT_FindPatrolLocation → Move To → Wait
| Node | Settings |
|---|---|
| BTT_FindPatrolLocation | Patrol Key = PatrolLocation |
| Move To | Blackboard Key = PatrolLocation, Acceptable Radius = 50 |
| Wait | Wait Time = 2.0, Random Deviation = 0 |

Move To's Acceptable Radius is "how close counts as arrived." Rather than matching the position exactly, it stops once it gets reasonably close.
Finally, add "Event On Possess" to BP_EnemyAIController's EventGraph and connect it to "Run Behavior Tree." "BTAsset" is BT_Enemy.

On Possess is called when the controller takes over a Pawn. Starting the tree at that point means patrol begins with the enemy it controls already decided.
Compile, save, and Play. Success is the enemy walking, waiting 2 seconds on arrival, then walking to the next spot. There is no spotting logic yet, so it keeps patrolling even if you approach.
Remember the player on the Blackboard when spotted
With patrol working, add sight to the enemy. AI Perception is the system for receiving information such as what was seen or heard. We use sight only.

Set the sight distance and angle
Add an "AI Perception" component to BP_EnemyAIController. Add one "AI Sight config" to "Senses Config" and set the following.
| Item | Value and meaning |
|---|---|
| Sight Radius | 1500: the maximum distance for newly spotting a target |
| Lose Sight Radius | 1800: the distance at which a spotted target is lost |
| Peripheral Vision Half Angle | 60: 60 degrees each side of front, about 120 degrees total |
| Detection by Affiliation → Detect Neutrals | On: also targets those without team settings |
| Starts Enabled | On |
Sight Radius 1500 is 15 m. Lose Sight Radius is not a setting for seeing through walls. Hide behind a wall that blocks line of sight and it loses you even within range. Make the test wall one that Blocks the "Visibility" channel.
On the player's BP_ThirdPersonCharacter, set the following.
- Add "Player" to the Actor "Tags" in "Class Defaults." This is separate from Component Tags.
- Add "AI Perception Stimuli Source," turn on "Auto Register as Source," and add "AISense_Sight" to "Register as Source for Senses."
Stimuli Source is the part that registers something as detectable. Adding the Player tag here lets you tell whether a detected Actor is the player. Do not put the Player tag on BP_Enemy.
Receive the target and the sight result from the notification
Create a function "ApplySightUpdate" in BP_EnemyAIController. It takes two inputs: "SeenActor" (Actor Object Reference) and "bSensed" (Boolean). A Boolean is a true/false value, representing whether the target is visible here.
From the "+" on "On Target Perception Updated" in the AI Perception component's details, add an event and call ApplySightUpdate.
- The event's Actor → the function's SeenActor.
- Stimulus → Break AIStimulus → Successfully Sensed → the function's bSensed.

A Stimulus is the data bundling this detection result. "Successfully Sensed" true is a spotted notification; false is a lost-sight notification. Since we configured sight only, hearing notifications will not be mixed in.
Record and clear the target
Inside ApplySightUpdate, first pass SeenActor to "Actor Has Tag"'s Target with "Tag" set to Player. Connect the result to a Branch's Condition. Connect the white exec line from the function entry into this Branch, and advance only the True case into a second Branch. Pass bSensed to that second Condition.
SeenActor and bSensed come from the output pins at the function entry. Actor Has Tag is a node that inspects a value, so no white exec line runs through it. Reading white lines as order of operations and colored lines as data such as targets and results makes the connections easier to follow.

On the second Branch's true side, create "Set Value as Object" from the return of "Get Blackboard" (Target is Self). "Key Name" is TargetActor and "Object Value" is SeenActor.

On the false side, confirm "is the target we lost the one we are currently chasing?" before clearing it.
- From Get Blackboard's return, create "Get Value as Object" with "Key Name" set to TargetActor.
- Connect that Return Value and SeenActor to the two inputs of "Equal (Object)." This node returns true if they point at the same instance.
- Place a third Branch and connect Equal (Object)'s result to its Condition. Connect the white exec line from the bSensed Branch's False output.
- From the third Branch's True, go to "Clear Value" with "Target" set to Get Blackboard's return and "Key Name" set to TargetActor. Leave the False side unconnected.

The Target for Get Value as Object, Set Value as Object, and Clear Value is the Blackboard Component you got from Get Blackboard. That is the part for reading and writing this AI's notes. It is not where you connect the enemy Character.
Clearing only when you lose the target you are chasing prevents another Actor's notification from wiping your chase target. Wire the store and clear logic inside the same ApplySightUpdate, onto the True and False sides of the bSensed Branch respectively.
Compile and save what you have. With BT_Enemy open during Play, success is TargetActor on the Blackboard becoming the player when spotted and returning to None when lost. None means "no referenced target is stored." The enemy's behavior can still be patrol only at this stage.
Add the chase branch and switch mid-action
Instead of an attack, make a Task that logs
Create a new Task and name it "BTT_Attack." Connect "Event Receive Execute AI" to "Print String" with "In String" set to "Attack." Then connect to "Finish Execute" and turn on "Success." Compile and save.

Now you can confirm on screen or in the Output Log when the tree chose the attack Task. We deal no damage here; we watch whether the decision-making works.
Put the chase steps to the left of patrol
Connect another Sequence to BT_Enemy's Selector. Set "Node Name" to "Chase and attack" and place it to the left of patrol. Its children are "Move To," "BTT_Attack," and "Wait," in that order.

Set the chase-side Move To as follows.
| Setting | Value |
|---|---|
| Blackboard Key | TargetActor |
| Acceptable Radius | 200 |
| Reach Test Includes Agent Radius | Off |
| Reach Test Includes Goal Radius | Off |
| Track Moving Goal | On |
| Allow Partial Path | Off |
With both capsule radii excluded from the arrival test, it advances to the next Task once it is within about 2 m. Track Moving Goal updates the path to follow a moving target. Allow Partial Path permits "a path that only gets partway to the goal"; we leave it off here.
Set the post-attack Wait to "Wait Time" 1.0 and "Random Deviation" 0. While the target is nearby, it now waits about a second between attacks. If you add real damage logic, you also need checks on the target, distance, and facing at attack time.
Abort the current behavior when the condition changes
Right-click the "Chase and attack" Sequence and add "Add Decorator" → "Blackboard." Specify the following.
| Setting | Value |
|---|---|
| Blackboard Key | TargetActor |
| Key Query | Is Set |
| Notify Observer | On Result Change |
| Observer Aborts | Both |
Is Set is the condition that checks whether a chase target is stored. But adding a condition alone cannot stop a patrol that is already running.
That is what Observer Aborts (the setting that watches a condition and aborts) is for. Both includes the two directions of aborting we want here.
- When a target is stored, abort the patrol on the right and switch to the chase on the left.
- When the target is cleared, abort this chase branch and return to patrol.

The flow is now "the spotting logic writes to the Blackboard → the condition changes → the running branch switches." The sight logic updates target information, and the behavior switch is left to the tree.
Run it and compare the tree against the values
Play with BT_Enemy open and select the placed enemy instance from the debug target at the top of the editor. Watching the highlighted running node and the Blackboard's current values, try the following in order.
| Action | Expected result |
|---|---|
| Wait outside the enemy's vision | It repeats patrol Move To and Wait |
| Step into the enemy's front arc | TargetActor becomes the player and it switches to chase |
| Stop nearby | "Attack" appears at roughly 1-second intervals |
| Block the enemy's line with a wall | TargetActor becomes None and it returns to patrol |
Stopping Play and changing Observer Aborts to "None" to try again is also instructive. Step in front of the enemy while it is in the patrol Wait and you can see that the target information updates but the running wait is not interrupted. Set it back to Both when you are done.

| Problem | Where to look |
|---|---|
| The enemy doesn't move at all | The green NavMesh, AI Controller Class, Auto Possess AI, the On Possess startup |
| It stops after picking a patrol point | Whether the Task's Patrol Key is PatrolLocation, and whether Finish Execute was called |
| TargetActor stays None | The player's Actor Tag, Sight distance and angle, Detect Neutrals, Stimuli Source |
| The target is stored but patrol doesn't abort | The left-right branch order, the Decorator's Observer Aborts |
| It keeps chasing after losing sight | Whether it reaches Clear Value, and whether that Target is the Blackboard |
| It spots you through walls | Whether the wall's Visibility is Block |
| Attack prints continuously | Whether the post-attack Wait Time is 1.0 |
If you add more enemies, TargetActor goes into a separate Blackboard per enemy. When checking, also confirm the debug target is the enemy you intended.
If you want it to investigate the last known position after losing sight, or to react to sound, continue to the AI Perception article. To have it pick hiding spots, EQS is next; to see an approach built around states and transitions, StateTree is the other candidate.
Bonus: Good to Know Up Front
- Order is priority: a Behavior Tree tries children from the left. Put "chase when spotted" to the left of "patrol." Even with the condition correct, reversed order will not behave as you expect
- Line up the references first: if even one connection among AI Controller, Behavior Tree, and Blackboard is missing, nothing runs even though it looks assembled. Match the Blackboard Key's name and type with the Task and Decorator too
- When it won't switch, look at Observer Aborts: aborting a chase immediately, or switching the instant you spot something — these "interrupt mid-action" behaviors are decided by the difference between
Self,Lower Priority, andBoth - Add one thing at a time: finish patrol first, watch it work, then add the chase branch. Building it all at once leaves you unable to tell what caused what
Summary
In a Behavior Tree, a Selector picks the behavior and a Sequence walks through its steps. A Decorator reads the decision material stored on the Blackboard, and Tasks handle movement and waiting.
What is especially worth confirming with this enemy is that "the player was spotted" and "stop patrolling and chase" are separate things. First, did the value change; second, did the branch switch. Checking in that order keeps causes traceable as behaviors multiply.