Combat Roles

Documentation Unreal Engine AI Combat Roles

Multi-enemy coordination with role-based behavior, slot management, and fitness evaluation.


Coordinating multiple enemies so they don't all attack at once. Some flank, some wait, some support.

Player
Attacker
Waiter
Waiter
Flanker
Combat Slots
Attackers:1 / 1
(Others must wait)
Enemies dynamically swap roles based on slot availability and priority.

When to Use This

  • Any game with multiple enemies at once that shouldn't all attack simultaneously
  • Soulslike encounters where enemies take turns
  • Group tactics with specialized roles (tank, flanker, support)
  • Dynamic difficulty by adjusting how many attackers are allowed

This system can be used independently of the other plugin systems.


Core Concepts

The Role System

Instead of all enemies rushing the player, each gets assigned a role:

RoleBehaviorTypical Actions
AttackerClose-range aggressiveMelee combos, pressure
FlankerCircles wide, attacks from anglesSide attacks, backstabs
WaiterMaintains distance, watchesOccasional pokes, ready to swap in
SupporterStays back, buffs/debuffsRanged attacks, healing allies
ElitePriority attacker, ignores some limitsBoss-tier behavior

Roles are dynamic. Enemies swap based on distance, fitness scores, and availability.

Slot Management

The subsystem limits how many enemies can attack at once:

// In your AIConfig:
MaxAttackers = 2;        // Only 2 enemies attack at a time
MaxTotalCombatants = 5;  // Only 5 enemies engage at all

When one Attacker finishes or dies, a Waiter can take its place.

Fitness Evaluation

"Who should be the next Attacker?" is decided by Fitness Evaluators. These are scoring functions that run on each AI:

// Built-in evaluators:
DistanceEvaluator     // Closer = higher fitness
HealthEvaluator       // Healthier = higher fitness  
RandomEvaluator       // Adds unpredictability
CooldownEvaluator     // Fewer actions on cooldown = higher fitness

The AI with the highest combined fitness score gets priority for open slots.

Role-Based ActionSets

Each role can have a different ActionSet:

Attacker  → DA_ActionSet_Aggressive (fast attacks, short cooldowns)
Flanker   → DA_ActionSet_Flanking (side-specific attacks)
Waiter    → DA_ActionSet_Patient (defensive, occasional pokes)
Supporter → DA_ActionSet_Ranged (projectiles, buffs)

When an AI's role changes, its ActionSet automatically swaps to match.


Quick Setup

1. Create an AICombatConfig

Right-click → Miscellaneous → Data Asset → AICombatConfig

2. Configure Roles

// Example configuration:
AutoRegisterForCombatRoles: true
 
AllowedRoles:
  - SEC.Role.Attacker
  - SEC.Role.Flanker  
  - SEC.Role.Waiter
 
Priority: 0              // Lower = higher priority for slots
PreferredRole: SEC.Role.Attacker

3. Set Up Fitness Evaluators

Add evaluators to determine role assignment priority:

FitnessEvaluators:
  - DistanceEvaluator (Weight: 1.0)
  - HealthEvaluator (Weight: 0.5)
  - RandomEvaluator (Weight: 0.2)

Evaluators are instanced UObjects. You can create custom ones by inheriting from URoleEvaluator.

4. Map Roles to ActionSets

ManageActionSetsAutomatically: true
DefaultActionSet: DA_ActionSet_Attacker
 
RoleActionSets:
  SEC.Role.Waiter   → DA_ActionSet_Patient
  SEC.Role.Flanker  → DA_ActionSet_Flanking
  SEC.Role.Supporter → DA_ActionSet_Ranged

5. Assign to Enemy

In your Enemy Blueprint → AIConfig → Set to your AICombatConfig

See Configuration Reference for the complete structure.


How Role Assignment Works

1. Enemy spawns, registers with AICombatRoleSubsystem
2. Subsystem evaluates all registered enemies
3. Fitness scores calculated for each
4. Roles assigned based on:
   - Slot availability (MaxAttackers limit)
   - Fitness scores
   - Distance priority
   - Preferred role
5. Each enemy's ActionSet/MovementProfile updated to match role
6. Re-evaluation happens when:
   - An enemy dies
   - An Attacker finishes their attack
   - Periodic tick (configurable)

Custom Fitness Evaluators

Create your own scoring logic:

UCLASS()
class UMyCustomEvaluator : public URoleEvaluator
{
    GENERATED_BODY()
    
public:
    virtual float EvaluateFitness(const FRoleEvaluationContext& Context) override
    {
        // Return 0.0 - 1.0
        // Higher = more fit for the role
        
        // Example: Prioritize enemies the player can't see
        if (!PlayerCanSeeMe(Context.Pawn))
            return 1.0f;
        return 0.3f;
    }
};

Add it to your AICombatConfig's FitnessEvaluators array.


Runtime Control & API

You can control the role system dynamically during gameplay using the AI Combat Role Subsystem. This is great for boss fights, cutscenes, or changing difficulty on the fly.

Blueprint Functions

Configuration Overrides:

  • Set Reassignment Interval: Change how often the system re-evaluates roles.
  • Set Min Time In Role: Stop enemies from switching roles too quickly (hysteresis).
  • Set Role Limit Override: Change the max number of actors allowed in a role.
    • Example: Allow 3 Attackers instead of 1 for a "Enrage" phase.
  • Clear Role Limit Override: Reset limits back to project settings.
  • Update Config: Swap the entire configuration struct at runtime.

Manual Control:

  • Force Assign Role: Lock an AI into a specific role.
    • Useful for: Scripted events where an enemy must wait or taunt.
  • Unlock Role: Return the AI to the automatic pool.
  • Force Reassignment: Trigger an immediate re-evaluation of all AI.
// Example: Enrage phase - Allow more attackers
UAICombatRoleSubsystem* RoleSys = GetWorld()->GetSubsystem<UAICombatRoleSubsystem>();
RoleSys->SetRoleLimitOverride(FGameplayTag::RequestGameplayTag("SEC.Role.Attacker"), 3);
RoleSys->ForceReassignment();

Role Syncing

When an enemy's role changes (e.g., from Waiter to Attacker), their abilities and movement behavior need to update to match.

Automatic Syncing

If you use AEnemyControllerBase, this happens automatically. The controller monitors role changes and updates the components for you.

Manual Syncing (Custom Controllers)

If you are building your own controller, use the SEC Combat Role Sync Library. It handles the complex logic of finding the right asset for the role.

Nodes:

  • Sync All For Combat Role: Updates both ActionSets and Movement profiles.
  • Sync Action Set For Role: Updates only abilities.
  • Sync Movement Profile For Role: Updates only movement.
// Inside your Custom Controller: On Role Changed Event
USECCombatRoleSyncLibrary::SyncAllForCombatRole(
    this,               // Controller
    GetPawn(),          // Pawn
    NewRoleTag,         // The new role
    MyEnemyAIConfig     // The config asset
);

Debug Tools

Console Commands:

SEC.Debug.Roles.ShowAssignments 1   // Display current role assignments
SEC.Debug.Roles.LogTransitions 1    // Log role changes

In AICombatConfig:

bDebugLogRoleChanges: true

Integration Points

SystemHow Combat Roles Uses It
Action SystemSwaps ActionSet when role changes
Movement SystemDifferent roles have different positioning profiles
Threat DetectionThreatened AI may be deprioritized for Attacker role