[UE5] AI Perception Basics: An Enemy That Chases What It Sees and Searches What It Loses

Created: 2026-07-20Last updated: 2026-09-06

Set up sight and hearing with UE5's AI Perception and receive spotted, lost, and heard separately. Diagrams adding an investigate branch to a Behavior Tree so the enemy waits 5 seconds at the clue and returns to patrol.

You hide behind a pillar and the enemy tracks your exact position anyway. Or the moment you vanish it returns to patrol as if nothing happened. Building enemy-like behavior means separating what it knows from what it has lost track of .

AI Perception is UE's mechanism for giving AI sight and hearing. You receive notifications like "I saw someone" and "there was a noise" and connect them to the enemy's decisions.

An enemy noticing someone who entered its view and not noticing someone outside the range

What You'll Learn

  • A design splitting noticing, remembering, and acting
  • Deciding Sight's distance, angle, and occlusion
  • Telling spotted, lost, and heard apart from the notification
  • Adding a branch that investigates a clue and then returns to patrol

We build an enemy that chases what it spots, investigates the clue position when it loses sight, waits 5 seconds, and returns to patrol . Even without seeing you, a noise sends it to that position.

Sponsored

Split noticing, remembering, and acting

When footsteps are heard, what AI Perception reports is "a sound happened at this place". Whether to wait there or walk toward it is decided separately.

AI Perception senses, the Blackboard records, and the Behavior Tree picks the behavior
MechanismIts role here
AI PerceptionGathers information about what was seen and heard
BlackboardThe notes storing the target and the place to check
Behavior TreeReads the notes and picks chase, investigate, or patrol

The hands-on continues from Behavior Tree Basics. We use the BP_Enemy , BP_EnemyAIController , BB_Enemy , and BT_Enemy built there. Get the enemy patrolling and chasing the player on sight first.

This article extends the sight settings and the ApplySightUpdate function. It matters that the previous notification logic and the new logic do not run at the same time . The connections to replace are shown in the steps.

Prepare the watcher and the watched

The watcher is BP_EnemyAIController . Open it and add AI Perception from "Add Component". If you added it in the Behavior Tree article, use that component.

The AI Controller is the side operating the enemy character. Gathering the perception settings here makes it easy to pass what it receives to the Blackboard.

Attaching the sensing component to the AI Controller and registering the player as a Sight target

On the watched side, BP_ThirdPersonCharacter , confirm the following.

  1. Add Player to the Actor "Tags" in "Class Defaults". That is separate from Component Tags.
  2. Add an AI Perception Stimuli Source .
  3. Turn on "Auto Register as Source".
  4. Add AISense_Sight from the "+" on "Register as Source for Senses".

A Stimuli Source is the component for "registering this Actor as a perception target". Beyond attaching it, you specify which senses it registers for.

Standard Sight also has default behavior that auto-registers Pawns (including Characters). We register explicitly here so the steps do not depend on settings differences. Use the same method when making an ordinary Actor a sight target.

Hearing is not a mechanism where footsteps arrive automatically just from registering. We add the step that notifies from the sound-producing side later.

Decide distance, angle, and occlusion with Sight

Add an AI Sight config to AI Perception's "Senses Config". If one exists, open it and match these values. Distances are in cm.

SettingValue hereMeaning
Sight Radius1200The distance at which it first spots you. 12 m
Lose Sight Radius1600The distance boundary for losing someone spotted. 16 m
Peripheral Vision Half Angle6060 degrees to one side of forward. 120 total
Auto Success Range from Last Seen Location-1Disables the keep-seeing exception
Max Age5Expiry of old perception data. Not a behavior wait
Starts EnabledOnEnables sight from the start of play

Two radii exist so the boundary does not flicker

If the spotting distance and the losing distance were the same, crossing that boundary would toggle spotted and lost repeatedly. Widening the losing distance means someone once spotted stays seen even at a slightly greater distance .

First spotting at 12 m; once spotted, distance is allowed up to 16 m while line of sight holds

That does not mean anything inside Lose Sight Radius is visible through walls. Beyond distance, the orientation and occlusion conditions must be met too.

Half Angle is half of the total field of view

Half Angle is half the angle. 60 means 60 degrees left and 60 degrees right of forward, 120 total. 90 gives 180 degrees ahead, not sight all the way behind.

A field of view spreading 60 degrees each side of forward, for 120 degrees total at a half angle of 60

Make the visible wall and the sight-blocking wall agree

Occlusion is line of sight being blocked by a wall or similar. Standard Sight tests whether the space between the watcher and the target is blocked.

For the experiment, place a large box or wall the player can hide behind entirely. Set its collision to Block Visibility . Block means blocking tests on that channel.

In projects that changed the channel used, match "Project Settings" → "AI System" → "Default Sight Collision Channel". Details are in the collision channel article.

Check the affiliation setting and the Player tag

Even with the distance and angle right, the affiliation to detect setting can exclude a target. "Detection by Affiliation" is that filter.

EntryTarget
Detect EnemiesHostile parties
Detect NeutralsNeutral parties
Detect FriendliesAllies

A player with no team set, as here, is treated as neutral. Turn Detect Neutrals on for Sight. Being an enemy Blueprint does not make UE automatically assign the player to a hostile team.

Including neutral targets in perception, then selecting the player with the Player tag

Including neutrals means things other than the player get reported too. So after receiving a notification, let only targets with the Player tag through using Actor Has Tag .

The affiliation setting decides "what the sensor picks up"; the Actor Tag decides "which of those the game logic uses". Splitting them also prevents enemies chasing each other.

Split notifications by which sense they came from

Add an event from the "+" on On Target Perception Updated in AI Perception's details. Use the existing one if there is one.

The event gives you the target Actor and a Stimulus summarizing this perception result. Do not overthink "stimulus": it is notification data holding when, where, and what was sensed .

Create Break AIStimulus from Stimulus to extract its contents.

EntryMeaning here
Successfully SensedWhether this stimulus was sensed. A true/false value
Stimulus LocationThe position recorded in the stimulus. Stored as the investigation point
TagThe name given to a sound. Useful for kinds like Footstep or Gunshot

For sight, Successfully Sensed true means spotted and false means lost. But sound notifications arrive at the same event . Treating every false as "lost the player" risks stopping the chase merely because sound information went stale.

Sight and hearing notifications arrive at the same event. Separate the sense kind before reading Successfully Sensed

The node that inspects the kind is Get Sense Class for Stimulus . Pass it a Stimulus and it returns a class representing the sense kind such as AISense_Sight or AISense_Hearing . The concrete wiring comes in the hands-on.

Note that sight notifies about visibility changes, and hearing about newly reported sounds. It is not a per-frame position-tracking event.

Make a noise the AI can hear with the N key

Playing footsteps through the speakers and telling the AI "footsteps happened here" are separate. Let's try the notification alone first, without real audio.

On the listening side's AI Perception, add an AI Hearing config to "Senses Config".

SettingValue here
Hearing Range2000 (20 m)
Detect NeutralsOn
Max Age5
Starts EnabledOn

Turn Detect Neutrals on for Hearing too , not just Sight.

Next open the player's BP_ThirdPersonCharacter Event Graph. Add a keyboard N event and connect a white exec wire from "Pressed" to Report Noise Event .

PinConnection / value
Noise LocationGet Actor Location's Return Value (Target is Self)
Loudness1.0
InstigatorSelf
Max Range0
TagFootstep
Calling Report Noise Event from the N key, passing the player's location and Self

Instigator is "the Actor that made this sound". Here it is the player, so pass Self. The receiving side checks whether that target has the Player tag.

Loudness is the sound's strength, and Max Range is a distance cap set on the sound side. We use Loudness 1 and Max Range 0, imposing no cap on the sound side, so the listener's Hearing Range covers 20 m . The relationship between loudness and distance changes with setting combinations, so leaving Loudness at 1 and adjusting the range is clearest at first.

Playing audio and notifying the AI are separate. Under these settings, listeners within 20 m react

Standard Hearing is not blocked simply because a wall blocks Visibility the way Sight is. Reacting to sound through a wall is normal in this experiment. To model how much a wall dampens sound, add a separate test.

To link it to footsteps later, call the same notification from Animation Notify instead of the N key.

Sponsored

Hands-On: investigate the clue and return to patrol

Now we write perception notifications into the Blackboard and connect them to the enemy's behavior. The distinction here is chasing someone you can see versus investigating a place you know they were .

The flow of patrol, spotting, chasing, losing sight, and waiting 5 seconds at the clue position

While investigating it stays at that place for 5 seconds. We do not add a search animation that walks around yet; we confirm the behavior switch.

1. Add a note for the investigation point

Add LastKnownLocation to BB_Enemy with type Vector . A Vector here is the type representing a position with X, Y, and Z. Together with the two from the Behavior Tree article, we use these three.

Key nameTypeWhat it stores
TargetActorObject (Base Class: Actor)The target currently visible and being chased
LastKnownLocationVectorThe investigation coordinates from sight or sound
PatrolLocationVectorThe next patrol point

An Actor reference points at the same target even as it moves. A Vector is the coordinate at the moment it was stored. When relying on sound alone, use the coordinate so the enemy does not track the current position of someone it has not seen.

2. Make one entry point for notifications

Prepare these three functions in BP_EnemyAIController . The existing ApplySightUpdate gets one more input and updated contents.

FunctionInputs
HandlePerceptionNoticeNoticeActor: Actor Object Reference, NoticeStimulus: AIStimulus
ApplySightUpdateSeenActor: Actor Object Reference, bSensed: Boolean, SensedLocation: Vector
ApplyNoiseUpdatebSensed: Boolean, NoiseLocation: Vector

First connect the event's exec output to HandlePerceptionNotice , passing Actor to NoticeActor and Stimulus to NoticeStimulus. Replace the previous event's direct connection to ApplySightUpdate with this.

Passing the target and stimulus from the event to HandlePerceptionNotice

Inside HandlePerceptionNotice, wire this order.

  1. Pass NoticeActor to Actor Has Tag 's Target with Tag Player .
  2. Connect the result to a Branch 's Condition. Connect the function entry's exec output to the Branch and end on the False side.
  3. From True, connect to Get Sense Class for Stimulus 's exec input, passing NoticeStimulus to Stimulus.
  4. Create Equal (Class) from Return Value with the compared class AISense_Sight . Connect the result to the next Branch's Condition, and Get Sense Class for Stimulus's exec output to that Branch.
  5. On True, call ApplySightUpdate. On False, use another Equal (Class) and Branch to check for AISense_Hearing and call ApplyNoiseUpdate only when true.
After the Player tag check, inspecting the stimulus's sense class and splitting into Sight and Hearing handling

The values passed to the two calls are below. Create Break AIStimulus from NoticeStimulus to extract them.

Function calledValues to pass
ApplySightUpdateSeenActor = NoticeActor, bSensed = Successfully Sensed, SensedLocation = Stimulus Location
ApplyNoiseUpdatebSensed = Successfully Sensed, NoiseLocation = Stimulus Location

Actor Has Tag and Equal (Class) inspect values and take no white exec wire. Get Sense Class for Stimulus, however, has white exec pins. Do not skip it just because of the name Get.

At this stage, placing Print Strings at both functions' entries showing Sight and Hearing confirms things. Compile and save each Blueprint, then Play and try stepping into view, hiding behind a wall, and pressing N. Once eye and ear notifications arrive separately, you can add the next logic.

The Player Actor Tag says "who", the sense class says "eye or ear", and the sound Tag Footstep says "what kind of sound". Renaming the sound tag to Gunshot leaves the sense kind as Hearing.

3. Write the visible target and the coordinate to investigate separately

When reading and writing the Blackboard in the AI Controller, build nodes from Get Blackboard (Target = Self) 's Return Value . The Target for Set Value as Object , Set Value as Vector , Get Value as Object , and Clear Value is all this Blackboard Component.

That Blackboard Component is the part for operating on this running enemy's notes . It is not where you connect the BB_Enemy asset from the Content Browser or the enemy Character. Keep the existing On Possess → Run Behavior Tree (BT_Enemy) .

If ApplySightUpdate still holds the Behavior Tree article's logic, replace it with the following. Connect the entry to a Branch with bSensed as Condition. Since the shared entry already checked the Player tag, this function handles the perception result.

True: the target became visible

  1. Set Value as Object with Key Name TargetActor and Object Value SeenActor.
  2. Then Clear Value with Key Name LastKnownLocation .

Once the target is visible, chasing takes priority and the old investigation point is cleared.

Storing the spotted target in TargetActor and clearing the old LastKnownLocation

False: lost the target you were chasing

  1. Read TargetActor with Get Value as Object and compare it with SeenActor using Equal (Object) .
  2. Connect the result to a Branch's Condition, and route the bSensed False exec wire into that Branch.
  3. Only on True, write SensedLocation to LastKnownLocation with Set Value as Vector.
  4. Then clear TargetActor with Clear Value. Do nothing if the comparison is false.
On losing the same target, storing the investigation coordinate and then clearing the chase target

We use the position recorded in that sight notification as the investigation point. Perception updates at intervals, so it does not exactly match the last on-screen frame's position. Calling Get Actor Location on a hidden target would let the AI chase a current position it should not know, so we use the stored coordinate.

Writing the coordinate first and clearing the chase target after means the next investigation point is ready the moment the chase ends. We compare that it is the same target so another Actor's notification does not clear the chase target.

Hearing: investigate the sound position only when nothing is visible

Wire ApplyNoiseUpdate as follows.

  1. Connect the entry to a Branch with bSensed as Condition. Do nothing on the False side.
  2. On True, read TargetActor with Get Value as Object and check its Return Value with Is Valid .
  3. If there is no valid target, write NoiseLocation to LastKnownLocation with Set Value as Vector. If there is a target, do nothing.
Sensing a sound and writing the investigation point only when no visible chase target exists

Is Valid checks whether a reference is valid. Use the version with exec pins here and continue to the store logic from the "Is Not Valid" output. Notifications where the sound information went stale do not rewrite the investigation point.

That way, footsteps while chasing a player right in front of you do not switch the enemy to investigating.

4. Make a Task that clears the note when the investigation ends

From BT_Enemy 's "New Task", choose BTTask_BlueprintBase and create BTT_ClearLastKnown . Add a variable TargetKey of type Blackboard Key Selector with "Instance Editable" on.

Key Selector is the type for specifying "which note to clear" from a Task placed in the tree. Connect these three nodes with white exec wires.

Event Receive Execute AI → Clear Blackboard Value → Finish Execute

Pass a Get of TargetKey to Clear Blackboard Value's Key and turn on Finish Execute's Success.

The Task clears the Blackboard value named by TargetKey and returns success with Finish Execute

In the Controller we operated by Key Name, but inside a BTTask you use Blackboard nodes that take a Key Selector . The names are similar, so compare where you are and the Key pin's type.

5. Insert the investigate branch between chase and patrol

Add a Sequence to BT_Enemy 's Selector and name it "Investigate". Arrange it so the order is chase, investigate, patrol from left to right .

A Behavior Tree choosing between three branches: chase, investigate, and patrol, from left

Keep the Behavior Tree article's "chase and attack" and "patrol". Confirm the chase side has TargetActor Is Set with Observer Aborts Both.

Add a Blackboard Decorator to the "Investigate" Sequence. A Decorator is the condition for using that branch.

SettingValue
Blackboard KeyLastKnownLocation
Key QueryIs Set
Notify ObserverOn Value Change
Observer AbortsBoth

Is Set means "is an investigation point present". Both lets a condition change abort the running branch or the patrol to its right. On Value Change watches not only presence but coordinate changes, so a noise at a new place can restart the investigation.

Under the Sequence, connect Move To, Wait, and BTT_ClearLastKnown left to right. All three are children of the Sequence. They are not chained parent to child.

The investigate Sequence with Move To, Wait 5 seconds, and the clear Task as children. Move To has Force Success
NodeSettings
Move ToBlackboard Key = LastKnownLocation, Acceptable Radius = 100
Move To arrivalTurn off both Reach Test Includes Agent Radius and Goal Radius
Move To pathAllow Partial Path off, Observe Blackboard Value on
WaitWait Time = 5, Random Deviation = 0
BTT_ClearLastKnownTarget Key = LastKnownLocation

An acceptable radius of 100 cm makes it wait within about a meter of the spot. The 5 seconds start after the movement finishes.

Also right-click the investigate Move To and add Force Success from "Add Decorator". It makes the tree treat a failed move as success and continue. It is not a feature that forces movement to the destination.

If the point was unreachable, it waits 5 seconds there and ends the investigation. Without this, a movement failure stops the Sequence, the note never gets cleared, and the same investigation repeats.

Clearing the value with BTT_ClearLastKnown drops the investigate condition and returns it to patrol. Writing (0, 0, 0) means "investigate the origin", a different thing, so remember use Clear when you want it empty .

6. Compare the movement against the notes

Compile each Blueprint and save everything including the Behavior Tree. For the test area, use a wide floor at one height with a single wall you can hide behind entirely. Confirm the NavMesh connects the enemy and the player with P .

Open BT_Enemy during Play and select the placed enemy's Controller in "Debug Object" to see the running branch and Blackboard values.

What to tryWhat you should see
Step within 12 m in frontThe player enters TargetActor and it switches to chasing
Move behind the wallThe investigation coordinate is set and TargetActor empties
Stay hiddenThe enemy goes to the point, waits 5 seconds, returns to patrol
Show yourself while it waitsThe wait aborts and it switches to chasing
Press N where it cannot see youWithin 20 m the Hearing notification arrives and it investigates
Press N at another spot while it investigatesLastKnownLocation changes and it investigates the new place

Making noise repeatedly while moving keeps updating the investigation point, so it rarely returns to patrol. On your first check, press N once and stay quiet until the enemy finishes waiting.

If something is off, check in the order does the notification arrive → do the notes change → does the tree switch → can it move .

SymptomWhere to check
No Sight logView angle, distance, occluders, Sight's Detect Neutrals, target registration and Player tag
No Hearing logThe N input, Report Noise Event running, Instigator, Hearing settings
Logs appear but notes do not changeGet Blackboard's Target, Key Name spelling, launch via Run Behavior Tree
Notes change but it keeps patrollingBranch left-to-right order, the Decorator's Key and Observer Aborts
It never returns from investigatingThe Task after Wait, Target Key, Finish Execute
It keeps chasing behind the wallSight's occlusion setting and Auto Success Range, whether TargetActor cleared
It spots you from directly behindWhether the enemy itself turned, whether you mixed up sight and hearing, the actual view angle

If movement itself stops, confirm the foundation with the N-key movement experiment in the NavMesh article.

Sponsored

Perception expiry and search time are separate

It is tempting to think "I set Max Age to 5, so it searches for 5 seconds", but these two have different responsibilities.

Perception's expiry for old information and the Behavior Tree's post-arrival 5-second wait, on separate timelines

Max Age is the expiry of the perception information Perception holds. 0 means no expiry. To use the behavior that forgets stale Actor information, also enable "Forget Stale Actors" under "Project Settings" → "AI System".

Wait, on the other hand, is a wait time as enemy behavior. This article writes "move to the investigation point and wait 5 seconds" in the tree, then clears LastKnownLocation. Perception-side information expiring does not automatically clear a value you saved to the Blackboard yourself.

Actually visualize the field of view

The Gameplay Debugger during Play also shows perception state. It opens with ' (apostrophe) by default, and numpad 4 displays Perception information. If a different keyboard layout prevents it opening, check "Activation Key" in the project's Gameplay Debugger settings.

Narrowing or widening the view angle changes how far around you can get behind it. Changing Half Angle from 60 → 30 and trying to circle around to the enemy's front makes the difference clear.

The "keep seeing" exception changes the stealth feel

Auto Success Range from Last Seen Location sets how close to the last-seen position someone must be to keep counting as seen . It is not a distance from the AI itself.

Leave it at -1 while testing occlusion and adjust once the basic behavior works. Dominant Sense likewise selects which sense takes priority at a queried target position; it does not automatically decide our Blackboard write order or behavior priority.

Bonus: Good to Know Up Front

  • Visible but unnoticed : Sight is affected by angle and occlusion , not just distance. Even directly in front, an intervening mesh's Collision settings can prevent detection
  • Affiliation can wait : handling teams in Blueprint alone is where people get stuck. Use Detect Neutrals first and judge friend or foe with tags or interfaces
  • Notifications arrive on change : it is not reported "visible" every frame. It arrives the moment it spots and the moment it loses. To keep chasing, remember the last seen position yourself
  • Perception expiry and search time are separate : how long Perception remembers and how long the AI keeps searching are decided independently

Summary

Chase a visible target as an Actor, and use a coordinate as the clue when you lose sight or only hear a noise. With that difference, an enemy can distinguish "I know where they are now" from "they were around here".

Try hiding, making noise, and showing yourself again while watching the notification kinds and Blackboard values. Once you understand why chase and investigate switch, you can tune noise loudness and search time to fit your game.

Further Reading

Unreal Engine Notes in this section98