Targeting System
Documentation Unreal Engine AI Targeting Multi-Player
Give every enemy something to fight: register the player once, pick how each AI chooses, and the pack engages.
Nothing in SEC runs until an enemy has something to fight. Register the player once, and each enemy takes a target from the pool by whatever rule you gave it.
Set it up
45 seconds- 1
Register the player as a combat target
On the player pawn's Event BeginPlay, add Get AICombat Role Subsystem, then call Register Combat Target with Target Actor set to Self and Auto Assign Unassigned ticked.Player pawn · Event BeginPlayAICombatRoleSubsystemRegister Combat TargetTarget is AICombat Role SubsystemTargetTarget ActorSelfAuto Assign UnassignedReevaluate ExistingSearch the context menu forRegister Combat Target, under AI | Combat Role | Targeting. AI decisions run on the server, so branch on Has Authority before the call. - 2
Tell each enemy how to choose
Open the enemy's Enemy AI Config and set Target Selector to Closest Target Selector.EnemyConfig_Grunt▾Combat RoleTarget SelectorNoneTarget FilterNoneIgnore Target RedistributionAll three have working defaults. Target Selector is the one worth filling in once a fight holds more than one enemy. - 3
Play, and watch it engage
Press Play and runSEC.Debug.Role 1. Every enemy draws its name and combat role above its head, coloured by role. One that never took a target reads None.
Target Selector ships empty on the AI Config, and Default Target Selector ships empty in project settings. With neither filled in, an enemy takes the first target it may fight, whether that target was already in the pool or registered long after the enemy started running, as long as Register Combat Target is called with Auto Assign Unassigned ticked. That carries a single enemy and a single player. Fill one of the two in once several enemies share a fight or several players are registered, because then which target each enemy takes is a decision worth making.
Pick how each enemy chooses
Viewport
LVL_SEC_Showcase>Targeting
Selector:
Target 1(2)
Target 2(3)
E1
E2
E3
E4
E5
Target Counts
Target 1: 2
Target 2: 3
Event Log●
No events yet
Click targets to eliminate. System periodically re-evaluates assignments based on strategy.
| Selector | Picks | Use it for |
|---|---|---|
| First Target Selector | The first registered target | Single player, one player pawn |
| Closest Target Selector | The nearest target | Melee chasers |
| Balanced Target Selector | The target with fewest enemies on it, staying put while tied for least loaded | Co-op fairness |
| Random Target Selector | One target at random | Chaotic encounters |
| Fixed Target Selector | The one actor carrying a tag you name | A training dummy, livestock, a siege gate |
| Awareness Filtered Target Selector | Wraps another selector and offers it only targets this enemy has perceived | Stealth |
Where the selector comes from
Combat Role
Target Selector
None
Target Filter
None
Ignore Target Redistribution
Target Selector on the AI Config answers first. Leave it empty and the project setting answers instead, under Project Settings > Plugins > Soulslike Enemy Combat > Combat Roles > Target Selection.
Target Selection
Default Target Selector
None
Default Target Filter
None
Set the project default once for a whole game, then override it on the configs that want something else.
Fight only what it has seen
Set Target Selector to Awareness Filtered Target Selector, and fill in Awareness Config on the same AI Config. See Awareness System.
Details
Awareness Filtered Target Selector
Awareness Filter
Min Required State
Lost
Inner Selector
None
Instanced selector on the Enemy AI Config. Needs a SEC Awareness component on the AI controller.
| Field | What to do with it |
|---|---|
| Min Required State | How much the enemy has to know before a target counts. Lost, the default, keeps it engaged through the grace period after it loses sight. Detected demands current sight. Suspicious lets a heard target through. |
| Inner Selector | Runs on what survives the filter, and takes any selector including another of these. Leave it empty for the nearest candidate. |
Without an awareness component on the AI controller the filter warns once, then passes the whole list through unfiltered, so the enemy fights everything. Controllers built on the plugin's base class carry one.
Hunt one named actor
Fixed Target Selector pins an enemy to a single actor and nobody else, the player included.
- Select the target actor in the level. Open the Actor category in the Details panel, click the advanced arrow, and add a name under Tags.
- Register that actor with Register Combat Target, the same node the player uses.
- Set Required Tag on the selector to the same name.
Keep Current Target If Untagged is on, so an enemy already fighting keeps the fight if something strips the tag mid-combat. Leave Required Tag empty and the enemy targets nothing at all, which is deliberate rather than a fallback to whoever is nearest.
Nesting this inside an Awareness Filtered Target Selector gives an enemy that fights nothing, because that wrapper offers only targets the enemy has perceived and a training dummy is never sensed. Tick Always Aware on the awareness config, or use the Fixed selector on its own.
Decide who an enemy will fight at all
A selector picks from what an enemy is willing to fight, and a filter decides that first. The built-in answer refuses the enemy itself and anything it counts as an ally, and lets the rest through. An actor with no team declared reads as fair game, which is the ordinary case for a player pawn that never sets one.
Add a SEC Team component to declare sides. Characters built on the plugin's enemy base class carry one already.
| Field | Default | What to do with it |
|---|---|---|
| Team Id | 1 | 0 to 254. Use 0 for the player and 1 for enemies. 255 means no team. |
| Free For All | off | Every other actor reads hostile, this actor's own team included, and Team Id stops deciding anything. |
| Ignore Player | off | Team 0 and any player-controlled pawn read as neutral, so this actor leaves the player alone. |
| Excluded Team Ids | empty | Actors on these teams read as neutral to this actor. |
| Allowed Hostile Team Ids | empty | Fill it and only these teams can read hostile; everything else reads neutral. Leave it empty to filter with Excluded Team Ids instead. |
| Ignore Neutrals | off | Keeps a teamless actor neutral while Free For All is on. Outside Free For All a teamless actor already reads neutral. |
| Fight Only | empty | Pick one actor in the level and this pawn hunts that alone, whatever the rows above say. Its own team still reads friendly. |
These rules change what an enemy will fight, not what its weapon will hit. A swing that catches a bystander still lands, because a melee trace decides what it damages through its own Team Filter.
Several targets at once
Each registered target owns its own role pool, so two players each cap at three Attackers independently.
For co-op, register every player pawn and set Default Target Selector to Balanced Target Selector. Enemies spread themselves across the players, and each one stays with its current target while that target is among the least loaded.
To pin a boss to whoever it first engaged, tick Ignore Target Redistribution on its AI Config. That enemy sits out the automatic redistribution passes, both the reassignment timer and the Reevaluate Existing pin, and keeps its target until the target dies. The hand-driven nodes in Assigning targets by hand below move it anyway.
When a target dies
Unregister the target, or let it be destroyed, and the sequence runs on its own:
- Every enemy assigned to it loses its target and its focus, and its combat role resets to None.
- Each of those controllers fires On Combat Target Lost, carrying the target it lost.
- Each one runs its selector again and takes another registered target if one is available.
- On Combatants Orphaned fires once, carrying the lost target and everyone freed by it.
To send an enemy back to patrol instead of straight onto the next player, bind On Combat Target Lost on the pawn controller's SEC Combat Controller component, or implement the On Combat Target Lost event on an Enemy Controller Base subclass.
Debug it
SEC.Debug.Role 1 // Name and combat role above each enemy, coloured by role
SEC.Debug.Decision 1 // Distance, angle, line of sight, speed and threat it scores against
SEC.Debug.Teams 1 // Team ID, Free-For-All, and what the exclusion rules turn aside
SEC.Debug.Awareness 1 // What each enemy knows about its target
SEC.Debug.LogRoleAssignments 1 // Role assignment scoring, 1 for basic and 2 for verbose
SEC.Debug.All 1 turns every overlay on at once, and SEC.Debug.WatchPawn <name> narrows them to one enemy. Each overlay also has a checkbox on its own component, so one enemy can be isolated without the console.An enemy holding role None while a target is registered never took one. Check its Target Selector first, then its team rules with
SEC.Debug.Teams 1.AdvancedEnemies that spawn before the player
An enemy registered while the target pool is empty stays idle. Every call to Register Combat Target gives each idle enemy another chance, running its own filter and selector over the pool, so a player who appears late is picked up without extra wiring. An enemy whose team rules turn that target aside stays idle rather than being handed it.
That idle pass needs a selector. With none configured anywhere it returns nothing, which is the case the warning at the top of this page covers.
Auto Assign Unassigned adds an immediate role evaluation on top of the idle pass. Reevaluate Existing also forces enemies that already have a target to run their selector again, for a target that registers closer than the one they picked.
To pin one enemy to a pool at the moment it registers, set Initial Target (Runtime Only) on the role registration parameters before registration. It skips the selector entirely.
AdvancedRedistributing targets on a timer
The reassignment timer updates roles only, unless you tick Reevaluate Targets On Reassignment under Project Settings > Plugins > Soulslike Enemy Combat > Combat Roles > Timing:
Timing
Role Reassignment Interval
8
Min Time In Role
8
Reevaluate Targets On Reassignment
It has an effect only while more than one target is registered. Each cycle re-runs every enemy's selector, skipping any with Ignore Target Redistribution, then evaluates roles. An enemy keeps what it has when its selector answers with the same actor or with nothing.
Set Reevaluate Targets On Reassignment toggles the same flag at runtime.
AlternativeAssigning targets by hand
For scripted encounters, drive the pools directly instead of leaving it to selectors. Every one of these lives on the AICombat Role Subsystem. Reevaluate All Targets is the only one that honours Ignore Target Redistribution; the rest carry out the order on a pinned enemy too.
| Node | Does |
|---|---|
| Assign Combatant To Target | Puts one enemy in one pool. Pass nothing to unassign. It carries out the order as given without asking the enemy's filter, so check the pairing yourself. |
| Reassign Combatant Target | Re-runs the selector for one enemy. On failure it clears the assignment, resets the role to None, and fires the target-lost path. |
| Reevaluate All Targets | Re-runs the selector for everyone, skipping Ignore Target Redistribution. |
| Balance Combatants Across Targets | Round-robin across every registered target, ignoring selectors. Each enemy is still only handed a target its own team rules allow. |
| Transfer Combatants To Target | Moves a whole pool, for a player-death handoff. An enemy that may not fight the destination is left where it was. |
| Set Primary Target And Assign All | Puts everyone on one target, for a boss or a VIP. An enemy whose team rules refuse that target keeps what it had. |
| Select Target For | Runs the enemy's configured selector over a candidate list of your own, such as sphere overlap results. Returns nothing when no selector is configured. |
AdvancedWriting your own selector
Subclass Target Selector in Blueprint or C++ and override Select Target. It receives the controller, the candidate list, and a context the subsystem builds for it:
Target Selection Context
Current Target
None
Combatant Count Per Target
0 Map elements
Distance Squared Per Target
0 Map elements
Is Target Loss Reselection
The candidate list arrives with everything its filter refuses already removed, the enemy itself included while the built-in answer is in play, so a selector decides preference rather than permission.
Return nothing while Is Target Loss Reselection is true to take over the handoff after a target dies. The subsystem leaves the enemy unassigned and your On Combat Target Lost handler runs the retreat, the delay, or the re-aggro itself.
AdvancedWriting your own filter
Subclass SEC Target Filter in Blueprint and override Can Fight, for a charmed enemy that turns on its own side. Set it on the AI Config's Target Filter for one enemy, or as Default Target Filter in project settings for all of them.
Add a parent call first to keep the built-in answer and narrow it from there. Without one, the override replaces the self check, the ally check and the exclusion rules together.
Keep any property you add on a single-segment category (
Filter, not Filter|Advanced). The class expands inline wherever it is set, and a nested category makes the details panel recurse until it overflows.One filter answers for every targeting decision: the candidate list a selector sees, an actor joining the shared pool, and the awareness pass that wakes an enemy up. Exclusion rules bite through it and nowhere else, so a hand-rolled friend-or-foe check reads an excluded actor as neutral and lets it straight through.
AdvancedTeam reads and damage filtering
Team lookups read a SEC Team component on the actor, on its pawn, or on its controller, then fall back to the engine's own team agent. An actor with neither is neutral.
| Node | Returns |
|---|---|
| Get Team Id | 0 to 254, or 255 for no team |
| Set Team Id | True when a component or the engine agent accepted the ID |
| Has Team | Whether the actor has anything other than 255 |
| Get Relation | Friendly, Hostile, or Neutral, answered by the first actor's own rules |
| Are Friendly / Are Hostile | Same question as a bool |
| Can Damage | Whether a damage causer may hit a target under a filter mode |
Damage filtering is separate from targeting. Can Damage takes one of four modes: No Filter, Enemies Only, Friendlies Only, Neutral Only. The pawn's melee trace component exposes the same choice:
Details
SEC Melee Trace
Damage
Team Filter
No Filter
Damage category on the wielder trace component. Filters who can be hit, separate from combat target selection.
AdvancedSubsystem events
| Event | Fires when |
|---|---|
| On Combat Target Registered | A target joins the pool |
| On Combat Target Unregistered | A target leaves it |
| On Combatants Orphaned | A target is lost, carrying it and every controller freed by it |
| On Combat Role Changed For Target | A role changes, carrying which pool it happened in |
The full list is on Combat Roles.
AdvancedQuerying the pools
| Node | Returns |
|---|---|
| Get All Combat Targets / Has Combat Target | The registered target pool |
| Get Combatant Target | One enemy's assigned target |
| Get Combatants For Target | Everyone in that target's pool |
| Get Role Count For Target | How many of a role that pool is using |
Set Combat Target and Get Combat Target are deprecated and warn on compile. Set Combat Target calls Register Combat Target with auto-assign on; Get Combat Target returns the first registered target. Use Get Combatant Target or Get All Combat Targets instead.
Where targeting connects
| System | How |
|---|---|
| Combat Roles | Every target owns an independent role pool. |
| Awareness System | The Awareness Filtered Target Selector gates candidates on what the enemy has perceived. |
| Movement System | Movement steers relative to the controller's focus actor, which is set when a target is assigned. |
| Action System | Actions score against the assigned target, and one action can be handed another through contextual execution. |
| Multiplayer | Register each player pawn on the server. |