How the enemy AI works, and what it hears¶
The enemy that ships with the template is the Warden: a robot that patrols, notices you by sight or by sound, and fires a laser at you. It is made of four pieces, and only one of them makes decisions.
- The enemies:
Content/MPFriendslop/Blueprints/AI/ - The tuning:
Blueprints/DataAssets/Enemy/ - The noise component:
Blueprints/ActorComponents/BP_NoiseComponent
This page is the mental model. The pages after it are the recipes.
The four pieces¶
| Piece | What it owns |
|---|---|
BP_EnemyBase |
The body of any enemy. It holds the current state, the suspicion value, the laser aim and the health. Every player sees these values |
BP_Warden |
A child of BP_EnemyBase. Mesh, animation, laser effect, sounds and camera shakes. It decides nothing, it only shows what the body says |
BP_WardenController |
The brain. It runs on the server only: it sees, hears, picks a target, moves and fires |
DA_Enemy_Warden |
A BP_EnemyDataAsset with the numbers: speeds, ranges, timings, damage. It goes in Enemy Data on the enemy |
BT_Warden and BB_Warden are in AI/Warden/Behavior/. The tree is deliberately small: it walks to the point the controller gives it, or waits. All the choices are in BP_WardenController, so that is the Blueprint to read.
The states¶
The current state is an E_EnemyState. The controller picks it every frame, on the server.
| State | What the Warden does | What moves it to the next state |
|---|---|---|
Patrol |
Walks its Patrol Points in order at Patrol Speed, pauses Patrol Wait Seconds at each one and looks around |
Hears a noise: Investigate. Sees you for Detection Seconds: Chase |
Investigate |
Walks to the noise | Arrives: Search |
Chase |
Walks to where it last saw you, at Chase Speed |
You are within Attack Range and visible: Attack. Loses sight of you for Sight Loss Grace Seconds: Search |
Attack |
Fires the laser and keeps near Preferred Combat Distance |
Loses sight of you for Sight Loss Grace Seconds: Search |
Search |
Walks to random points within Search Radius of your last known position |
Search Seconds run out: back to Patrol |
A noise heard while it is not patrolling extends the search. All these fields are on DA_Enemy_Warden.
What it sees¶
Sight is the AIPerception component of BP_WardenController: Sight Radius 2200, Lose Sight Radius 2400, Peripheral Vision Half Angle Degrees 65.
Not everything it sees is a target. A target is a pawn that:
- is controlled by a player,
- returns a
BP_VitalsSystemfromGetVitalComponent(BPI_VitalManagerInterface), - is alive, and not down (
GetIsDownonBPI_PlayerLifeState, read from its PlayerState).
Crouching makes a player harder to see. A crouching player is only seen within Crouched Sight Radius (1100, half the sight radius), and it takes Crouched Detection Seconds (1.5) instead of Detection Seconds (0.75) to be spotted. Both are on DA_Enemy_Warden. Crouching is read from the pawn's movement component, so it works on any Character of your own.
The nearest one wins. A player who dies or goes down is dropped, and the Warden goes to Search. The laser damages anything with a vital component that is in the beam, so a friend standing in front of you takes the hit.
The Warden also takes damage, from the guns and melee weapons of the template. At zero health it is removed. There is no death animation. See How weapons work.
The suspicion arc¶
While the Warden is building up detection, an arc above its head fills. The arc is sight only: a noise sends the Warden to Investigate straight away, without filling it. It is WBP_EnemyAwareness, shown by the AwarenessWidget component on BP_EnemyBase. It only shows between empty and full, and only to a player who can see the Warden. Each player draws it for themselves.
| Field | What it does | Shipped default |
|---|---|---|
Arc Color |
Colour of the fill | white |
Background Color |
Colour of the empty part | near black, 0.8 opacity |
Arc Radius |
Size of the arc | 42 |
Arc Thickness |
Thickness of the fill | 3 |
Background Thickness |
Thickness of the empty part | 6 |
These are on the widget, in Settings|Style. Its position above the head is the Location of the AwarenessWidget component.
What it hears¶
The Warden hears through the Hearing Range of its AIPerception, 2500. It only listens to noises tagged Footstep or Impact, and a noise behind a wall is not heard: the server checks the line from the Warden to the noise.
Noises come from BP_NoiseComponent. It is on BP_FriendslopCharacter and on BP_LootBase, and it makes them audible with no graph:
- a player makes a footstep noise every
Footstep Distancewalked on the ground (Crouch Step Distancecrouched), measured on the server, whatever the animation does; - a loot item that hits something makes an impact noise, louder the faster it hits.
A noise is heard within Hearing Range multiplied by its loudness, and never beyond its max range. The max range of a step follows the player's ground speed: 0 standing still, rising to Footstep Max Range at Footstep Full Range Speed. With the shipped speeds, a walking step (200 cm/s) is heard at 10 m, a sprinting step (500 cm/s) at 25 m, and a crouched step at about 1 m. The fields are in Settings|Noise:
| Field | What it does | Shipped default |
|---|---|---|
Footstep Loudness |
Loudness of a step | 1 |
Crouch Loudness |
Loudness of a crouched step | 0.05 |
Footstep Distance |
Distance walked, in cm, between two steps | 160 |
Crouch Step Distance |
The same, crouched | 110 |
Footstep Max Range |
Max range of a step at full speed, in cm | 2500 |
Footstep Full Range Speed |
Ground speed, in cm/s, at which a step reaches Footstep Max Range. Set it to your own character's sprint speed |
500 |
Impact Max Range |
Max range of an impact, in cm | 2500 |
Impact Reference Speed |
Impact speed, in cm/s, that gives a loudness of 1 | 600 |
To make a noise of your own, an alarm or a slammed door, call ReportNoise (Location, Loudness, Max Range, Tag) on a BP_NoiseComponent on the server, with the tag Impact. The Warden ignores any tag other than Footstep and Impact.
The dispatchers¶
| Dispatcher | On | When it fires | Fires on |
|---|---|---|---|
OnEnemyStateChanged |
BP_EnemyBase |
The state changed. Read the enemy's state to know the new one. Nothing in the template binds it: it is there for your music, HUD or voice lines | every player |
OnNoiseEmitted |
BP_NoiseComponent |
A noise was reported. Gives Location, Loudness and Tag |
server |