Networking/Replication

Overview Unreal Engine has been designed with networking in mind since Unreal Engine 1. This includes: Remote procedure calls (RPC). Replication of variables, including structs & dynamic arrays...

Updated over 4 years ago Edit Page Revisions

Overview

Unreal Engine has been designed with networking in mind since Unreal Engine 1.
This includes:

  • Remote procedure calls (RPC).
  • Replication of variables, including structs & dynamic arrays.
  • Dedicated server support.
  • VOIP

Creating a server

Listen

A listen server includes the host as a local player.
To launch a listen server, use the command line:
\ ?listen -game

Dedicated

A dedicated server does not include the host as a local player.
Renderering, audio, and anything else that isn't required is disabled to use a minimal footprint both in memory and cpu.

To launch a dedicated server, use the command line:
\ -server

Games that are ready to ship with cooked data will also include a standalone executable .
These are fully optimized for multiple instances per machine.

To launch a dedicated server using , use the command line:
\

Joining a server

To join a server at a specified IP address as a client, use the command line:
\ -game

To join a server via the in-game console, use the command:
open

Play In Editor Support

The editor includes built in support for networked games.

This is incredibly handy for quickly testing multiplayer games on a single host machine.

File:EditorPIEOptions.jpg

File:EditorPIEOptions.jpg

Blueprint support

Blueprints fully support replication, including replication notifications.
Replication notifications are handy if you want a client to do something when a variable updates.
eg. Play a particle effect if their health increases.

File:ReplicationBlueprintSupport.jpg

File:ReplicationBlueprintOnRep.jpg

C++ examples

Sync character health to all clients

YourCharacter.h

    UPROPERTY(Replicated)
    float Health;

YourCharacter.cpp

#include "UnrealNetwork.h"
// ...
void AYourCharacter::GetLifetimeReplicatedProps(TArray< FLifetimeProperty > &amp; OutLifetimeProps) const
{
    Super::GetLifetimeReplicatedProps(OutLifetimeProps);

    // Replicate to everyone
    DOREPLIFETIME(AYourCharacter, Health);
}

The DOREPLIFETIME macro is defined in UnrealNetwork.h, so make sure you #include it in your .cpp file. Your project will need a dependency on the "Engine" module in its Build.cs file to find the header, but most projects will have this dependency already.

Command from client to server

YourPlayerController.h

    bool bSomeBool;
    
    void SetSomeBool(bool bNewSomeBool);

    UFUNCTION(reliable, server, WithValidation)
    void ServerSetSomeBool(bool bNewSomeBool);
    virtual void ServerSetSomeBool_Implementation(bool bNewSomeBool);
    virtual bool ServerSetSomeBool_Validate(bool bNewSomeBool);

As of UE 4.15 the compile system adds the implementation and validation definitions for you. Making the code for the header as follows

    bool bSomeBool;
    
    void SetSomeBool(bool bNewSomeBool);

    UFUNCTION(reliable, server, WithValidation)
    void ServerSetSomeBool(bool bNewSomeBool);

You'll still need everything in the cpp file though!

YourPlayerController.cpp

void AYourPlayerController::SetSomeBool(bool bNewSomeBool)
{
    // Change the value of the bSomeBool property
    bSomeBool = bNewSomeBool;

    // If this next check succeeds, we are *not* the authority, meaning we are a network client.
    // In this case we also want to call the server function to tell it to change the bSomeBool property as well.
    if (Role < ROLE_Authority)
    {
        ServerSetSomeBool(bNewSomeBool);
    }
}

bool AYourPlayerController::ServerSetSomeBool_Validate(bool bNewSomeBool)
{
    return true;
}

void AYourPlayerController::ServerSetSomeBool_Implementation(bool bNewSomeBool)
{
    // This function is only called on the server (where Role == ROLE_Authority), called over the network by clients.
    // We need to call SetSomeBool() to actually change the value of the bool now!
    // Inside that function, Role == ROLE_Authority, so it won't try to call ServerSetSomeBool() again.
    SetSomeBool(bNewSomeBool);
}