Multiplayer Support

Documentation Unreal Engine AI Multiplayer Replication

Replication architecture, what runs where, and how to use the plugin in listen server and dedicated server games.


The plugin works in both listen server and dedicated server configurations. AI decisions run on the server, and relevant state replicates to clients automatically.

Overview

AI in Unreal Engine is inherently server-authoritative. AI controllers only exist on the server, and all decision-making happens there. The challenge for multiplayer is making sure clients have enough information to display what the AI is doing (animations, VFX, UI indicators) without duplicating the logic.
SoulslikeCombat handles this by replicating output state, not logic. The server runs the full decision pipeline, and lightweight replicated components on the pawn broadcast the results to clients.

Architecture: What Runs Where

Server Only

These components live on the AI controller and only exist on the server:
ComponentPurpose
SECCombatControllerComponentAIConfig resolution, combat role handling, sync
ActionEvaluationComponentScores and selects actions
MovementEvaluatorComponentTactical positioning
ThreatDetectionComponentTracks player camera attention
AICombatRoleSubsystemAssigns roles across all AI
This is the brain. Clients never run action evaluation or movement scoring. SECCombatControllerComponent is the central integration point that connects all these systems together.

Replicated to Clients

These components live on the pawn and replicate automatically:
ComponentWhat Replicates
SECActionSetComponentCurrent action ID, execution state, active ActionSet reference, cooldown state
SECReactionSetComponentCurrent reaction ID, execution state, active ReactionSet reference, cooldown state
SECCombatRoleComponentCurrent combat role tag
BasicHealthComponentCurrent health value
SECWeaponBaseActor replication (attachment, visibility)
SECMeleeTraceComponentServer-authoritative only (traces run on server, damage applied on server)

Client-Side Available

Clients can read all replicated state and bind to delegates. This is enough for:
  • Health bars and damage numbers
  • Action name indicators ("Charging Heavy Attack...")
  • Role-based outline colors or overhead icons
  • Animation (handled by standard GAS montage replication)

Component Breakdown

Gameplay Abilities

All abilities derived from GameplayAbilityBase are configured with:
NetExecutionPolicy = EGameplayAbilityNetExecutionPolicy::ServerInitiated;
ReplicationPolicy = EGameplayAbilityReplicationPolicy::ReplicateYes;
This means:
  • Abilities are activated on the server
  • GAS replicates the ability state and montage playback to clients
  • Clients see the correct animations without any extra work

Melee Trace (SECMeleeTraceComponent)

Melee traces run only on the server. The component's TickComponent checks for authority before processing traces. Damage is applied server-side via ApplyDamage.
Clients see the attack animation (via GAS montage replication) but don't run traces. Hit reactions, damage numbers, and VFX should be driven by the replicated health change or gameplay cues.

Weapons (SECWeaponBase)

Weapons replicate as actors (bReplicates = true). Attachment to the character skeleton happens on the server and replicates to clients, so weapons are visible on all machines.

Health (BasicHealthComponent)

Health is replicated with OnRep. The OnHealthDecreased delegate fires on both server and clients because it is triggered inside OnRep_Health, not inside DecreaseHealth. This means client-side UI can bind directly:
HealthComponent->OnHealthDecreased.AddDynamic(this, &UMyWidget::OnDamaged);
// This fires on both server and clients when health drops.

Action State (SECActionSetComponent)

The SECCombatControllerComponent pushes execution events to the pawn's SECActionSetComponent, which replicates them:
// Server-side (automatic, handled by controller):
ActionSetComponent->NotifyActionStarted("HeavyAttack");
ActionSetComponent->NotifyActionCompleted("HeavyAttack", true);
 
// Client-side (read in widgets, HUD, etc.):
ActionSetComponent->OnActionExecutionStarted.AddDynamic(...);
ActionSetComponent->OnActionExecutionCompleted.AddDynamic(...);
ActionSetComponent->OnActionSetChanged.AddDynamic(...);
 
// Cooldown tracking (for ability cooldown UI):
ActionSetComponent->OnActionCooldownStarted.AddDynamic(...);  // (ActionId, Duration)
ActionSetComponent->OnActionCooldownExpired.AddDynamic(...);  // (ActionId)
float Remaining = ActionSetComponent->GetRemainingCooldown("HeavyAttack");
bool bOnCD = ActionSetComponent->IsActionOnCooldown("HeavyAttack");

Reaction State (SECReactionSetComponent)

The same bridge pattern applies to reactions. The SECCombatControllerComponent pushes reaction events to the pawn's SECReactionSetComponent:
// Client-side (read in widgets, HUD, etc.):
ReactionSetComponent->OnReactionExecutionStarted.AddDynamic(...);
ReactionSetComponent->OnReactionExecutionCompleted.AddDynamic(...);
ReactionSetComponent->OnReactionSetChanged.AddDynamic(...);
 
// Cooldown tracking:
ReactionSetComponent->OnReactionCooldownStarted.AddDynamic(...);
ReactionSetComponent->OnReactionCooldownExpired.AddDynamic(...);
float Remaining = ReactionSetComponent->GetRemainingCooldown("BlockReaction");

Combat Role (SECCombatRoleComponent)

The role subsystem assigns roles to controllers (server-only). When a role changes, the SECCombatControllerComponent writes it to the pawn's SECCombatRoleComponent, which replicates the tag:
// Client-side:
FGameplayTag Role = CombatRoleComponent->GetCombatRole();
CombatRoleComponent->OnCombatRoleChanged.AddDynamic(...);

Movement

MovementEvaluatorComponent runs on the server and feeds input to Unreal's CharacterMovementComponent (CMC). The CMC handles replication natively. Position, velocity, and rotation all sync to clients through Unreal's built-in character movement replication. No additional work needed.

Setup

If you're already using the plugin in single-player, there's almost nothing to change for multiplayer.

What You Need

  1. Register combat targets - In multiplayer, register each player pawn as a combat target. The Targeting System handles multi-target distribution automatically.
// In GameMode or Player setup:
UAICombatRoleSubsystem* Subsystem = GetWorld()->GetSubsystem<UAICombatRoleSubsystem>();
Subsystem->RegisterCombatTarget(PlayerPawn, /*bAutoAssignUnassigned=*/ true);
  1. Drive client UI from replicated state - Use the delegates on SECActionSetComponent, SECCombatRoleComponent, and BasicHealthComponent for client-side feedback.
  2. Damage handling - If you're using custom damage handling (not Unreal's built-in ApplyDamage), make sure your system is server-authoritative. The melee trace only runs on the server, so all hit events originate there.

What You Don't Need To Do

  • No need to configure replication on components - it's set up by default
  • No need to manually sync animations - GAS handles montage replication
  • No need to replicate movement - CMC does this natively
  • No need to run AI logic on clients - everything is server-authoritative

Common Multiplayer Patterns

Co-op with Target Distribution

// Register both players
Subsystem->RegisterCombatTarget(Player1);
Subsystem->RegisterCombatTarget(Player2);
 
// AI distributes across players using TargetSelectors
// See Targeting System docs for selector options

Client-Side Enemy HUD

// In your enemy health bar widget:
void UEnemyHUD::Setup(APawn* EnemyPawn)
{
    auto* Health = EnemyPawn->FindComponentByClass<UBasicHealthComponent>();
    Health->OnHealthChanged.AddDynamic(this, &UEnemyHUD::UpdateHealthBar);
    Health->OnHealthDecreased.AddDynamic(this, &UEnemyHUD::FlashDamage);
 
    auto* ActionSet = EnemyPawn->FindComponentByClass<USECActionSetComponent>();
    ActionSet->OnActionExecutionStarted.AddDynamic(this, &UEnemyHUD::ShowActionIndicator);
    
    auto* Role = EnemyPawn->FindComponentByClass<USECCombatRoleComponent>();
    Role->OnCombatRoleChanged.AddDynamic(this, &UEnemyHUD::UpdateRoleIcon);
}

Dedicated Server

No special configuration needed. The plugin is fully compatible with dedicated servers. AI controllers exist on the dedicated server, and all replicated state flows to connected clients.

Integration Points

SystemMultiplayer Relevance
Action SystemActions replicate via SECActionSetComponent
Combat RolesRoles replicate via SECCombatRoleComponent
Melee TraceServer-authoritative only, no client traces
Targeting SystemMulti-target handles co-op player distribution
Movement SystemRelies on CMC native replication