Networking Jan 1, 2026

Lesson 6: Multiplayer Networking & Replication

Master Unreal's replication system, implement advanced replication techniques, create reliable RPC systems, optimize network bandwidth, and handle lag compensation for multiplayer battle royale games.

By GamineAI Team

Lesson 6: Multiplayer Networking & Replication

Welcome to Advanced Networking!

Great progress! You've built player movement systems. Now it's time to master the networking layer that makes multiplayer games work smoothly. In this lesson, you'll dive deep into Unreal's replication system, learn advanced techniques, and optimize your game for 50-100 concurrent players.

Learning Objectives

By the end of this lesson, you will:

  • ✅ Master Unreal's replication system and architecture
  • ✅ Implement advanced replication techniques
  • ✅ Create reliable RPC systems for client-server communication
  • ✅ Optimize network bandwidth for large player counts
  • ✅ Handle lag compensation and client prediction
  • ✅ Build robust multiplayer synchronization systems
  • ✅ Debug and profile network performance

Part 1: Understanding Replication Fundamentals

Step 1: Replication Architecture Deep Dive

1.1 How Replication Works

Unreal's replication follows this flow:

Server (Authority)
  ↓
  Replicates State
  ↓
Clients (Receive Updates)
  ↓
  Interpolate & Display

Key Concepts:

Authority:

  • Server has authority over all game state
  • Server validates all actions
  • Server replicates state to clients

Replication:

  • Server sends state updates to clients
  • Clients receive and apply updates
  • Updates happen at network update frequency

Network Roles:

  • Authority: Server (source of truth)
  • Autonomous Proxy: Client controlling this actor
  • Simulated Proxy: Other clients' actors

1.2 Replication Properties

Properties marked with Replicated are automatically synced:

UPROPERTY(Replicated)
float Health;  // Automatically replicated

UPROPERTY(Replicated, BlueprintReadOnly)
int32 Score;   // Replicated and readable in Blueprint

Replication Conditions:

// Replicate always
UPROPERTY(Replicated)

// Replicate only to owner
UPROPERTY(Replicated, ReplicatedUsing = OnRep_Health)
float Health;

// Replicate only on initial spawn
UPROPERTY(Replicated, ReplicatedUsing = OnRep_Initialized)
bool bInitialized;

Step 2: Replication Functions

2.1 GetLifetimeReplicatedProps

This function defines what gets replicated:

void ABRCharacter::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
{
    Super::GetLifetimeReplicatedProps(OutLifetimeProps);

    // Always replicate
    DOREPLIFETIME(ABRCharacter, Health);
    DOREPLIFETIME(ABRCharacter, MaxHealth);

    // Replicate conditionally
    DOREPLIFETIME_CONDITION(ABRCharacter, Score, COND_OwnerOnly);
    DOREPLIFETIME_CONDITION(ABRCharacter, TeamID, COND_InitialOnly);
}

Replication Conditions:

  • COND_None: Always replicate
  • COND_InitialOnly: Only on initial spawn
  • COND_OwnerOnly: Only to owning client
  • COND_SkipOwner: To all except owner
  • COND_SimulatedOnly: Only to simulated proxies

2.2 OnRep Functions

Called when replicated properties change:

UPROPERTY(Replicated, ReplicatedUsing = OnRep_Health)
float Health;

UFUNCTION()
void OnRep_Health()
{
    // Called when Health changes on client
    UpdateHealthBar();
    PlayDamageEffect();
}

Part 2: Advanced Replication Techniques

Step 3: Replication Graph (For Large Player Counts)

3.1 Enable Replication Graph

For 50-100 players, use Replication Graph:

Project Settings:

  1. EditProject Settings
  2. EngineNetwork
  3. Enable "Use Replication Graph"

3.2 Custom Replication Graph

Create custom replication graph for optimization:

// BRReplicationGraph.h
UCLASS()
class MULTIPLAYERBATTLEROYALE_API UBRReplicationGraph : public UReplicationGraph
{
    GENERATED_BODY()

public:
    UBRReplicationGraph();

    // Grid node for spatial replication
    UPROPERTY()
    class UReplicationGraphNode_GridSpatialization2D* GridNode;

    // Always relevant node
    UPROPERTY()
    class UReplicationGraphNode_ActorList* AlwaysRelevantNode;

    virtual void InitGlobalGraphNodes() override;
    virtual void InitConnectionGraphNodes(UNetReplicationGraphConnection* ConnectionManager) override;
};

3.3 Spatial Replication

Optimize replication based on distance:

void UBRReplicationGraph::InitGlobalGraphNodes()
{
    // Create grid node for spatial replication
    GridNode = CreateNewNode<UReplicationGraphNode_GridSpatialization2D>();
    GridNode->CellSize = 10000.0f; // 10km cells
    GridNode->SpatialBias = FVector2D(0.0f, 0.0f);

    AddGlobalGraphNode(GridNode);
}

Step 4: Replication Frequency Optimization

4.1 Set Update Frequencies

Optimize update frequencies based on importance:

// In character constructor
GetCharacterMovement()->SetNetUpdateFrequency(30.0f); // 30 Hz for movement

// For less critical actors
SomeActor->SetNetUpdateFrequency(10.0f); // 10 Hz for props

4.2 Priority-Based Replication

Set replication priority:

// High priority (replicates more frequently)
SetNetPriority(2.0f);

// Low priority (replicates less frequently)
SetNetPriority(0.5f);

4.3 Custom Replication Conditions

Create custom conditions for optimization:

virtual bool IsNetRelevantFor(const AActor* RealViewer, const AActor* ViewTarget, const FVector& SrcLocation) const override
{
    // Only replicate if within 5000 units
    float Distance = FVector::Dist(SrcLocation, ViewTarget->GetActorLocation());
    return Distance < 5000.0f;
}

Part 3: RPC Systems

Step 5: Reliable RPCs

5.1 Server RPCs

Server RPCs are called from client, executed on server:

// Declaration
UFUNCTION(Server, Reliable, WithValidation)
void ServerFireWeapon(FVector Location, FRotator Rotation);

// Implementation
void ABRCharacter::ServerFireWeapon_Implementation(FVector Location, FRotator Rotation)
{
    // Validate on server
    if (!CanFire())
    {
        return;
    }

    // Execute on server
    FireWeapon(Location, Rotation);
}

bool ABRCharacter::ServerFireWeapon_Validate(FVector Location, FRotator Rotation)
{
    // Validate input
    return Location.IsValid() && !Rotation.ContainsNaN();
}

5.2 Client RPCs

Client RPCs are called from server, executed on clients:

// Declaration
UFUNCTION(Client, Reliable)
void ClientTakeDamage(float DamageAmount, FVector HitLocation);

// Implementation
void ABRCharacter::ClientTakeDamage_Implementation(float DamageAmount, FVector HitLocation)
{
    // Execute on client
    PlayDamageEffect(HitLocation);
    UpdateHealthBar();
    PlayDamageSound();
}

5.3 NetMulticast RPCs

NetMulticast RPCs execute on server and all clients:

// Declaration
UFUNCTION(NetMulticast, Reliable)
void MulticastPlayExplosion(FVector Location);

// Implementation
void ABRWeapon::MulticastPlayExplosion_Implementation(FVector Location)
{
    // Execute on all clients
    SpawnExplosionEffect(Location);
    PlayExplosionSound(Location);
}

5.4 RPC Best Practices

Reliable vs Unreliable:

  • Reliable: Guaranteed delivery (use for important events)
  • Unreliable: Best effort (use for frequent updates)

When to Use Each:

  • Server RPC: Client actions that need server validation
  • Client RPC: Server events that affect client (damage, effects)
  • NetMulticast: Events visible to all players (explosions, spawns)

Part 4: Network Optimization

Step 6: Bandwidth Optimization

6.1 Reduce Replication Frequency

Lower frequency for less critical updates:

// Update every 0.1 seconds instead of every frame
SetNetUpdateFrequency(10.0f);

6.2 Compress Data

Use smaller data types when possible:

// Instead of float (32 bits)
UPROPERTY(Replicated)
uint8 HealthPercent; // 0-100 (8 bits)

// Convert when needed
float GetHealth() const { return HealthPercent / 100.0f * MaxHealth; }

6.3 Conditional Replication

Only replicate when needed:

UPROPERTY(Replicated, ReplicatedUsing = OnRep_TeamID)
int32 TeamID;

// Only replicate when team changes
void SetTeam(int32 NewTeam)
{
    if (TeamID != NewTeam)
    {
        TeamID = NewTeam;
        MarkDirtyForReplication();
    }
}

6.4 Replication Graph Optimization

Use spatial replication for large maps:

// Only replicate actors within view distance
virtual bool IsNetRelevantFor(const AActor* RealViewer, const AActor* ViewTarget, const FVector& SrcLocation) const override
{
    float Distance = FVector::Dist(SrcLocation, ViewTarget->GetActorLocation());
    return Distance < MaxReplicationDistance;
}

Step 7: Network Profiling

7.1 Enable Network Stats

In-game network statistics:

// Toggle network stats
static TAutoConsoleVariable<int32> CVarNetStats(
    TEXT("net.NetStats"),
    0,
    TEXT("Show network statistics")
);

7.2 Profile Replication

Use Unreal's network profiler:

  1. WindowDeveloper ToolsSession Frontend
  2. Enable "Network Profiler"
  3. Record session and analyze replication

7.3 Monitor Bandwidth

Check bandwidth usage:

// Get network stats
FNetworkStats NetworkStats;
GetWorld()->GetNetDriver()->GetNetworkStats(NetworkStats);

UE_LOG(LogTemp, Warning, TEXT("Incoming: %d KB/s, Outgoing: %d KB/s"),
    NetworkStats.IncomingBytesPerSecond / 1024,
    NetworkStats.OutgoingBytesPerSecond / 1024);

Part 5: Lag Compensation & Prediction

Step 8: Client Prediction

8.1 How Client Prediction Works

  1. Client predicts action locally
  2. Client sends action to server
  3. Server validates and executes
  4. Server sends correction if needed
  5. Client reconciles if prediction was wrong

8.2 Movement Prediction

Unreal handles movement prediction automatically:

// Enable prediction
GetCharacterMovement()->SetIsReplicated(true);
GetCharacterMovement()->SetNetUpdateFrequency(30.0f);

8.3 Custom Prediction

For custom actions, implement prediction:

void ABRCharacter::FireWeapon()
{
    // Predict locally
    if (IsLocallyControlled())
    {
        PredictFireWeapon();
    }

    // Send to server
    ServerFireWeapon();
}

void ABRCharacter::PredictFireWeapon()
{
    // Immediate local feedback
    PlayMuzzleFlash();
    PlayFireSound();
    SpawnProjectile();
}

Step 9: Lag Compensation

9.1 Server-Side Rewind

For hit detection, rewind time:

void ABRWeapon::ServerProcessHit(FVector_NetQuantize HitLocation, float ServerTime)
{
    // Rewind to when client fired
    float RTT = GetWorld()->GetFirstPlayerController()->GetPlayerState()->GetPing() / 1000.0f;
    float RewindTime = ServerTime - RTT;

    // Check hit at rewind time
    CheckHitAtTime(HitLocation, RewindTime);
}

9.2 Interpolation

Smooth movement between updates:

// Enable interpolation
GetCharacterMovement()->NetworkSmoothingMode = ENetworkSmoothingMode::Linear;
GetCharacterMovement()->NetworkSmoothingServerMaxDistance = 200.0f;

Part 6: Advanced Synchronization

Step 10: State Synchronization

10.1 Replicated State Machines

Synchronize state machines:

UENUM()
enum class EPlayerState : uint8
{
    Idle,
    Walking,
    Sprinting,
    Crouching,
    Jumping
};

UPROPERTY(Replicated, ReplicatedUsing = OnRep_PlayerState)
EPlayerState CurrentState;

UFUNCTION()
void OnRep_PlayerState()
{
    // Update state on client
    UpdateState(CurrentState);
}

10.2 Timestamp Synchronization

Synchronize timestamps for events:

UPROPERTY(Replicated)
float ServerTime;

void ABRGameMode::Tick(float DeltaTime)
{
    Super::Tick(DeltaTime);

    if (HasAuthority())
    {
        ServerTime = GetWorld()->GetTimeSeconds();
    }
}

10.3 Event Replication

Replicate important events:

// Replicate event
UPROPERTY(Replicated, ReplicatedUsing = OnRep_PlayerKilled)
bool bPlayerKilled;

UFUNCTION()
void OnRep_PlayerKilled()
{
    // Handle kill event on all clients
    PlayKillEffect();
    UpdateScoreboard();
}

Mini Challenge: Build Advanced Replication System

Task: Create a comprehensive replication system for your battle royale game.

Requirements:

  1. Implement Replication Graph for 50-100 players
  2. Create reliable RPC system for weapon firing
  3. Optimize bandwidth with conditional replication
  4. Implement client prediction for actions
  5. Add lag compensation for hit detection
  6. Create network profiling tools
  7. Test with 50+ simulated players
  8. Achieve <100KB/s per client bandwidth

Deliverables:

  • Custom Replication Graph implementation
  • Optimized RPC system
  • Network profiling results
  • Bandwidth optimization report
  • Multiplayer testing results

Pro Tips:

  • Start with basic replication, optimize later
  • Profile network usage early and often
  • Test with realistic player counts
  • Use Replication Graph for large player counts
  • Compress data when possible
  • Use conditional replication to reduce bandwidth
  • Test with high latency (200ms+) to ensure robustness

Common Mistakes to Avoid

1. Over-Replicating

  • ❌ Replicating everything at high frequency
  • ✅ Only replicate what's necessary, optimize frequencies

2. Not Validating RPCs

  • ❌ Trusting client input without validation
  • ✅ Always validate RPCs on server

3. Ignoring Bandwidth

  • ❌ Not monitoring network usage
  • ✅ Profile and optimize bandwidth regularly

4. Poor Lag Handling

  • ❌ Not accounting for network latency
  • ✅ Implement client prediction and lag compensation

5. Inefficient Replication

  • ❌ Replicating to all clients unnecessarily
  • ✅ Use conditional replication and Replication Graph

Troubleshooting

Q: High bandwidth usage with many players A: Use Replication Graph, reduce update frequencies, compress data, use conditional replication.

Q: Laggy movement in multiplayer A: Increase network update frequency, enable network smoothing, check server tick rate.

Q: RPCs not firing A: Check network roles, ensure RPCs are called correctly, verify server/client setup.

Q: Replication not working A: Check bReplicates flag, verify GetLifetimeReplicatedProps, ensure server authority.

Q: Clients see different game state A: Ensure server-authoritative, check replication conditions, verify RPC reliability.

Key Takeaways

Replication System: Master Unreal's replication architecture and properties ✅ Advanced Techniques: Use Replication Graph for large player counts ✅ RPC Systems: Create reliable Server, Client, and NetMulticast RPCs ✅ Optimization: Reduce bandwidth with frequency optimization and compression ✅ Lag Compensation: Implement client prediction and server-side rewind ✅ Synchronization: Synchronize state machines and events across network ✅ Profiling: Monitor and optimize network performance

What's Next?

In Lesson 7: Map Design & Procedural Generation, we'll:

  • Design battle royale map layouts
  • Implement procedural map generation
  • Create spawn point systems
  • Design shrinking zone mechanics
  • Build loot distribution systems
  • Create map landmarks and points of interest

Get ready to build the world where your battle royale takes place!

Additional Resources


Ready to continue? Move on to Lesson 7 to design your battle royale map!