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. 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 BeginPlay
    AICombatRoleSubsystem
    Register Combat Target
    Target is AICombat Role Subsystem
    Target
    Target ActorSelf
    Auto Assign Unassigned
    Reevaluate Existing
    Search the context menu for Register Combat Target, under AI | Combat Role | Targeting. AI decisions run on the server, so branch on Has Authority before the call.
  2. 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 Role
    Target SelectorNone
    Target FilterNone
    Ignore Target Redistribution
    All three have working defaults. Target Selector is the one worth filling in once a fight holds more than one enemy.
  3. 3

    Play, and watch it engage

    Press Play and run SEC.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.
SelectorPicksUse it for
First Target SelectorThe first registered targetSingle player, one player pawn
Closest Target SelectorThe nearest targetMelee chasers
Balanced Target SelectorThe target with fewest enemies on it, staying put while tied for least loadedCo-op fairness
Random Target SelectorOne target at randomChaotic encounters
Fixed Target SelectorThe one actor carrying a tag you nameA training dummy, livestock, a siege gate
Awareness Filtered Target SelectorWraps another selector and offers it only targets this enemy has perceivedStealth

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.
FieldWhat to do with it
Min Required StateHow 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 SelectorRuns 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.
  1. 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.
  2. Register that actor with Register Combat Target, the same node the player uses.
  3. 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.
FieldDefaultWhat to do with it
Team Id10 to 254. Use 0 for the player and 1 for enemies. 255 means no team.
Free For AlloffEvery other actor reads hostile, this actor's own team included, and Team Id stops deciding anything.
Ignore PlayeroffTeam 0 and any player-controlled pawn read as neutral, so this actor leaves the player alone.
Excluded Team IdsemptyActors on these teams read as neutral to this actor.
Allowed Hostile Team IdsemptyFill it and only these teams can read hostile; everything else reads neutral. Leave it empty to filter with Excluded Team Ids instead.
Ignore NeutralsoffKeeps a teamless actor neutral while Free For All is on. Outside Free For All a teamless actor already reads neutral.
Fight OnlyemptyPick 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:
  1. Every enemy assigned to it loses its target and its focus, and its combat role resets to None.
  2. Each of those controllers fires On Combat Target Lost, carrying the target it lost.
  3. Each one runs its selector again and takes another registered target if one is available.
  4. 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.
NodeDoes
Assign Combatant To TargetPuts 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 TargetRe-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 TargetsRe-runs the selector for everyone, skipping Ignore Target Redistribution.
Balance Combatants Across TargetsRound-robin across every registered target, ignoring selectors. Each enemy is still only handed a target its own team rules allow.
Transfer Combatants To TargetMoves 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 AllPuts everyone on one target, for a boss or a VIP. An enemy whose team rules refuse that target keeps what it had.
Select Target ForRuns 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.
NodeReturns
Get Team Id0 to 254, or 255 for no team
Set Team IdTrue when a component or the engine agent accepted the ID
Has TeamWhether the actor has anything other than 255
Get RelationFriendly, Hostile, or Neutral, answered by the first actor's own rules
Are Friendly / Are HostileSame question as a bool
Can DamageWhether 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
EventFires when
On Combat Target RegisteredA target joins the pool
On Combat Target UnregisteredA target leaves it
On Combatants OrphanedA target is lost, carrying it and every controller freed by it
On Combat Role Changed For TargetA role changes, carrying which pool it happened in
The full list is on Combat Roles.
AdvancedQuerying the pools
NodeReturns
Get All Combat Targets / Has Combat TargetThe registered target pool
Get Combatant TargetOne enemy's assigned target
Get Combatants For TargetEveryone in that target's pool
Get Role Count For TargetHow 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

SystemHow
Combat RolesEvery target owns an independent role pool.
Awareness SystemThe Awareness Filtered Target Selector gates candidates on what the enemy has perceived.
Movement SystemMovement steers relative to the controller's focus actor, which is set when a target is assigned.
Action SystemActions score against the assigned target, and one action can be handed another through contextual execution.
MultiplayerRegister each player pawn on the server.