APSDocs
Start here

Tutorial: a complete guard#

A guard with the whole loop: it patrols, checks out noises, chases what it sees, and when it loses you it searches where and how it lost you.

About 45 minutesAfter Get StartedBlueprint and a Behavior Tree, no C++
The 30-second version
  1. PatrolWalks its route.
  2. InvestigateHeard something: walks to the noise, looks, goes back. Doesn't chase.
  3. "Huh?"Saw something: turns to look, a moment before it commits.
  4. ChaseSure of you: runs you down.
  5. SearchLost you: searches the cover you hid behind, or the area of a sound, or follows where you ran.
  • Six parts, each ending with a checkpoint you can see in Play.
  • Events write to the Blackboard; the Behavior Tree reads it. No polling.
  • The clever part is the search: it branches on Get Loss Reason.

Part 1: the profile#

Create the profile as in Get Started (DA_Profile_Guard), open it and set these. Everything else keeps its default.

SectionSettingValue
RangesVision Max Range2200
RangesHearing Max Range1800
DetectionVision Half Angle Deg55
Detection › ConesEnable Peripheral Coneticked
Detection › EyesEye Turn Rate Deg Per Sec200
AwarenessSuspect Threshold0.18
AwarenessDetect Threshold0.40
AwarenessTrack Threshold0.65
LossVision Loss › Grace Time0.8
MemoryMin Time in Lost8
FairnessFirst Spot Reaction Time0.4
FairnessTelegraph Threshold0.22

Why these: a grace time of 0.8 s means a thin pillar doesn't erase you at once: the guard keeps staring at where you were. Min Time in Lost at 8 makes it really search instead of shrugging and walking off. The two Fairness values make detection feel readable rather than arbitrary.

Part 2: the guard and the player#

Open your AI character Blueprint (BP_Guard) and add APS Core with Profile set to DA_Profile_Guard, as in Get Started. Tick Show Visualizer too.

Every event in this tutorial is an APS Core event: select PerceptionCore (the APS Core) in the Components list, and in Details › Events click + next to it.

On your player character, add an APS Target Component and leave it as it is: it gives the guard five points on your skeleton to look for.

Part 3: make your footsteps audible#

Hearing does nothing until something makes a sound. On purpose: the guard hears exactly what you decide is audible.

  1. 1

    Make a sound type

    In the Content Browser: right-click → Miscellaneous → Data Asset → SoundTypeDefinition → name it DA_Sound_Footstep. Set:

    SettingValue
    Sound NameFootstep
    CategoryEnemy
    Alert LevelNormal
    Base Loudness1.0
    Max Range900
    Max LODTier1
  2. 2

    Add a footstep notify

    In your player's walk and run animations, add an anim notify named Footstep.

  3. 3

    Emit the sound

    In the player Blueprint, on that notify, call Emit Sound with Source = Self and Sound Type = DA_Sound_Footstep.

    Event AnimNotify_Footstep
      └─► Emit Sound   (Source: Self, Sound Type: DA_Sound_Footstep)

The Hearing & sounds page has everything else about sounds: walls, loudness, filters.

Part 4: push perception into the Blackboard#

The pattern: events write to the Blackboard, the Behavior Tree reads it. Never poll APS every tick from a service when an event already tells you.

4a. The Blackboard#

New Blackboard asset, BB_Guard, with these keys:

KeyType
TargetActorObject (base class Actor)
bHasTargetBool
LastKnownPositionVector
SearchRadiusFloat
LossReasonEnum: ELossReason
LossDirectionVector
LastCoverActorObject (base class Actor)
InvestigateLocationVector
PatrolPointVector

4b. Wire the events#

In BP_Guard's Event Graph, get the Blackboard once at Begin Play (Get Controller → cast to AIController → Get Blackboard) and promote it to a variable, BB.

Sure of you: set the target. On AI Detect fires when the guard is sure enough to act.

On AI Detect (Target, Threat Level, Stimulus)
  ├─► BB → Set Value as Object ("TargetActor", Target)
  └─► BB → Set Value as Bool   ("bHasTarget",  true)

It fires again if a chase slips back from Tracked to Detected; that just sets the same keys. Don't take the target from On Attention Changed: attention can go to someone the guard only suspects, or to a teammate.

Telegraph: the "huh?" moment. On AI Telegraph fires a moment before the guard commits.

On AI Telegraph (Target, Confidence)
  ├─► Play Sound at Location   (your "hmm?" cue)
  └─► AIController → Set Focus (Target)

Heard something: investigate, but don't interrupt a chase.

On AI Hear (Location, Loudness, Sound Type Name)
  └─► Branch: BB → Get Value as Bool ("bHasTarget") is false
              AND Sound Type Name is not None
        True → BB → Set Value as Vector ("InvestigateLocation", Location)

On AI Hear also fires between sounds while the noise builds up, with Sound Type Name None and the player's current position; the None check keeps the guard going to where the sound was.

Lost the target: stop chasing, set up the search. This is the important one.

On AI Lost (Target, Last Known, Predicted, Last Cover Actor)
  ├─ BB → Set Value as Bool   ("bHasTarget",        false)
  ├─ BB → Set Value as Vector ("LastKnownPosition", Last Known)
  ├─ BB → Set Value as Object ("LastCoverActor",    Last Cover Actor)
  ├─ BB → Set Value as Float  ("SearchRadius",      APS Core → Get Uncertainty Radius (Target))
  ├─ BB → Set Value as Enum   ("LossReason",        APS Core → Get Loss Reason (Target))
  └─ BB → Set Value as Vector ("LossDirection",     APS Core → Get Loss Direction (Target))

Gave up: clear everything.

On AI Forget (Target)
  ├─► BB → Set Value as Bool ("bHasTarget", false)
  ├─► BB → Clear Value ("TargetActor")
  ├─► BB → Clear Value ("LastKnownPosition")
  └─► AIController → Clear Focus

Part 5: the Behavior Tree#

New Behavior Tree, BT_Guard, using BB_Guard. The shape:

  • Root
    • Selector
      • bHasTarget is set CHASE
      • LastKnownPosition is set SEARCH
      • InvestigateLocation is set INVESTIGATE
      • PATROL
SelectorSequenceTaskDecorator

A Selector runs its children top to bottom and stops at the first that succeeds. The decorators get less specific as you go down, so the guard prioritises by itself: chase beats search, search beats investigate, investigate beats patrol.

Chase#

  • bHasTarget is set · Observer Aborts: Both Sequence
    • Move ToTargetActor, Acceptable Radius 150
    • Wait0.5

Observer Aborts: Both matters: it lets the tree drop the chase the moment the target is lost.

Search: the part that makes it look smart#

  • LastKnownPosition is set · Observer Aborts: Lower Priority Selector
    • LossReason == Occluded Sequence
      • Move ToLastKnownPosition
      • Move ToLastCoverActor: the very thing you hid behind
      • Wait2.0
      • Search Steptwice
    • LossReason == SoundFaded Sequence
      • Move ToLastKnownPosition
      • Wait3.0
      • Give Upinvestigate, don't chase
    • LossReason == OutOfRange Sequence
      • Move ToLastKnownPosition
      • Move Along Loss Direction
      • Search Stepthree times
    • Sequenceeverything else
      • Move ToLastKnownPosition
      • Search Stepthree times

For the loss reason decorators use a Blackboard decorator: Key LossReason, Key Query Is Equal To, and pick the value.

Task: Search Step (BTT_SearchStep)

Event Receive Execute AI
  └─► Get Random Reachable Point in Radius
        (Origin: LastKnownPosition, Radius: SearchRadius)
  └─► AI MoveTo (that point)
        On Success → Wait 1.0 → Finish Execute
        On Fail    → Finish Execute   // never stall the tree

SearchRadius grows the longer you stay hidden, so repeating this task spirals the search outward by itself.

Task: Move Along Loss Direction

Event Receive Execute AI
  └─► Branch: LossDirection → Is Nearly Zero
        True  → Finish Execute        // you weren't moving
        False → AI MoveTo (LastKnownPosition
                           + LossDirection × 600)
                → Finish Execute

Task: Give Up: clear LastKnownPosition and InvestigateLocation, then Finish Execute.

Investigate and patrol#

  • InvestigateLocation is set · Observer Aborts: Lower Priority INVESTIGATE
    • Move ToInvestigateLocation
    • Wait3.0
    • Give Up
  • PATROLyours, or this:
    • Pick Patrol PointGet Random Reachable Point in Radius around home → PatrolPoint
    • Move ToPatrolPoint
    • Wait2.0

Run it from the guard's AI Controller: Event On Possess → Run Behavior Tree (BT_Guard).

Part 6: watch what it's thinking#

You ticked Show Visualizer in Part 2: press Play and watch. The cones stop where its sight stops, its state and how sure it is float over its head, and the panel top right follows the guard you look at.

The APS Visualizer in the demo: a guard's cone, its lines to the points of the player it can see, and its panel
The Visualizer: the guard's view cone, a line to each point of you it can see (5/5 here), its state over its head, and the panel top right: Tracked, 90%, sense by sense.

Bind keys to turn the panel's pages and to freeze perception:

Key 1 → Get Visualizer Page → + 1 → Set Visualizer Page
Key 2 → APS Core → Debug Toggle Pause
PageLook for
SensesWhich sense drives detection, or why each silent one is silent
MemoryTime since sensed, how sure it still is, why it lost you
BrainThreat level, how it knows, relationship, role
EventsEvery event it fired, newest first: "is my Blueprint not bound, or did it never fire?"

Reading the Senses page in the middle of a chase is the fastest way to understand why the guard did what it did. For the answer in words, print Explain Perception (Target: your player): it lists every sense and says why it is or isn't contributing. More in The Visualizer.

What to change next#

TryWhat happens
Min Time in Lost to 20A far more persistent, tense guard
Tick Keyhole VisionYou can slip past at a distance, not up close
Add Vibration Sense with Vibration Min Speed 150Crouch-walking starts to matter
A second guard, Set Squad ID on both, tick Auto Share on DetectOne spots you, both close in
First Spot Reaction Time to 0Feel how much less fair it gets
A never-search zone around a roomA guaranteed safe space (recipe)

Ready-made settings for other kinds of AI (a dog, a zombie, a sniper, a horror stalker) are in Ready-made AI.

APS Advanced Perception System, by AuraGame. Unreal Engine 5.2 and later. These docs are for APS 3.0.
Questions and bug reports