How do you make an AI chase the player in Unreal Engine?
An AI-controlled enemy pawn must continuously chase the player around obstacles, re-pathing as the player moves. Wire this up the Behavior-Tree way: the AI perception system writes the player into a Blackboard key, and a MoveTo task drives navigation toward whatever that key currently references.
Requirements:
position — MoveTo must read the player's current location every tick.
- Store a live actor reference to the player (an
Objectkey), not a copied - Path over the NavMesh; do not teleport or set location directly each frame.
- The chase branch must stop cleanly once the key is cleared (player lost).
Complete the perception callback on the AI controller that records the target:
void AEnemyAIController::OnSeen(AActor* Actor, FAIStimulus Stimulus)
{
// your code here: write the perceived player into the "TargetActor"
// Blackboard key as a live Object reference
}
Write the implementation.
Store the player as an Object Blackboard key (set via perception), then a Behavior Tree Sequence runs a MoveTo task targeting that key. MoveTo uses the NavMesh to path each tick, and a Decorator aborts the branch when the key clears.
- ✗Teleporting via
SetActorLocationinstead of pathing throughMoveTo - ✗Caching the player's position once instead of re-reading the live key
- ✗Forgetting a NavMesh, so
MoveTosilently fails to move the pawn
- →How does
AcceptanceRadiusonMoveToaffect when the chase task succeeds? - →How would you make the AI predict and intercept the player's movement?
Idea
Chasing = "move to the Blackboard key that holds the player". Perception writes the player into the TargetActor key, and MoveTo re-paths over the NavMesh each tick.
Step 1. Controller writes the target into the Blackboard
// EnemyAIController.cpp
void AEnemyAIController::OnPossess(APawn* InPawn)
{
Super::OnPossess(InPawn);
RunBehaviorTree(ChaseTree);
// subscribe to perception
PerceptionComponent->OnTargetPerceptionUpdated.AddDynamic(
this, &AEnemyAIController::OnSeen);
}
void AEnemyAIController::OnSeen(AActor* Actor, FAIStimulus Stimulus)
{
if (Stimulus.WasSuccessfullySensed() && Actor->IsA(APlayerCharacter::StaticClass()))
{
// a live pointer to the player — NOT a copied position
GetBlackboardComponent()->SetValueAsObject(TEXT("TargetActor"), Actor);
}
}
Step 2. Behavior Tree
Selector
├─ Sequence [Decorator: Blackboard "TargetActor" IS Set]
│ └─ Task: MoveTo (Blackboard Key = TargetActor, AcceptanceRadius = 100)
└─ Task: BTTask_Patrol // fallback when there is no target
MoveTo re-paths by default while the target keeps moving. A Decorator with Observer Aborts = Self instantly cancels the branch when TargetActor is cleared.
Why an Object key, not a Vector
An Object key stores an actor reference, so MoveTo reads the player's current position every tick. A Vector key would freeze the position at the moment it was written.