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.
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:
| Role | Behavior | Typical Actions |
|---|---|---|
| Attacker | Close-range aggressive | Melee combos, pressure |
| Flanker | Circles wide, attacks from angles | Side attacks, backstabs |
| Waiter | Maintains distance, watches | Occasional pokes, ready to swap in |
| Supporter | Stays back, buffs/debuffs | Ranged attacks, healing allies |
| Elite | Priority attacker, ignores some limits | Boss-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 allWhen 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 fitnessThe 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.Attacker3. 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_Ranged5. 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: trueIntegration Points
| System | How Combat Roles Uses It |
|---|---|
| Action System | Swaps ActionSet when role changes |
| Movement System | Different roles have different positioning profiles |
| Threat Detection | Threatened AI may be deprioritized for Attacker role |
