This page looks best with JavaScript enabled

Networking with Unreal Engine 4: Data replication

 ·  ☕ 5 min read

Overview

The unreal engine comes with a lot of features, but one of the most compelling features is its built-in network support. It’s so naturally integrated with the engine/game code, it can be considered a first class feature.

From the Unreal Engine multiplayer docs:

The Replication system provides a higher-level abstraction along with low-level customization to make it easier to deal with all the various situations you might encounter when creating a project designed for multiple simultaneous users.

In Unreal Engine, Replication is the name for the process of synchronizing data and procedure calls between clients and servers.

The Replication system provides a higher-level abstraction along with low-level customization to make it easier to deal with all the various situations you might encounter when creating a project designed for multiple simultaneous users.

TLDR, Replication can be defined as the act of the server passing information or data to the client, we just indicate which value we can to synchronize and that’s it.

How to set a variable for replication

Compared to blueprints, setting a variable to be replicated in C++ it’s a little more complicated.

  • First you need to set the actor with bReplicates as TRUE (at the Class constructor or use SetReplicate() at runtime).
  • Second, add the keyword Replicated at the UPROPERTY macro.
1
2
UPROPERTY(Replicated)
int32 ReplicatedInt;
  • And finally, in the .cpp file, it’s necessary to specify that we want to replicated it using the DOREPLIFETIME macro with the method GetLifetimeReplicatedProps
1
2
3
4
5
6
void AExampleActor::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
{
    Super::GetLifetimeReplicatedProps(OutLifetimeProps);
    // Here we list the variables we want to replicate + a condition if wanted
    DOREPLIFETIME(AExampleActor, ReplicatedInt);
}

And with that, our variable is replicated every time it’s value change (well, kinda, we will see more about this later), just remember, It’s very important that you understand that the whole replication process only works from Server to Client and NOT the other way
round. In another entry we will learn how to get the server to replicate something that the client wants to share with others.

Using RepNotify

While using Replicated sends information from the server to a client, you can make us of a function that will be call after the value has been replicated (as a callback event in case some specific behavior is needed). In this case you can use ReplicatedUsing instead of Replicated.

1
2
3
4
5
6
7
8
/* Header file inside the class declaration (.h) */
// Create RepNotify Health variable
// (OnRep_ prefix is not necessary, but helps a lot to identify this kind of functions)
UPROPERTY(ReplicatedUsing=OnRep_Health)
float Health;
// Create OnRep Function | UFUNCTION() Macro is important! | Doesn't need to be virtual though (only if you are planning to override the default behavior)
UFUNCTION()
virtual void OnRep_Health();

From what I am seening with blueprints, the RepNotify can be (and must be apparently) triggered instantly after a change is made to a Replicated variable (otherwise, the notification will be triggered at the next network update).

Net Update Frecuency

Replicated variables usually are synchronized with the client as soon their values are changed, but that’s not what normally happens.

In order to keep a good network performance and avoiding bandwidth saturation, the engine can specify how often the new information can be considered to sended by the actor using NetUpdateFrequency. This is important since it’s used to determine how often per second an actor replicates to the clients. By default it’s set to 100 times per second.

Actor network roles

There are two properties on actor that are important when it comes to replication: Role and RemoteRole.

  • Who has the authority over the actor.
  • If the actor is replicated or not.
  • The replication mode.

ROLE_Authority
The actor can be controlled by the server (usually, when an actor has this role we can safely can asume we are in the server).
ROLE_AutonomousProxy
The client have authority over the actor, this usually means that the actor can be controlled by the client.
ROLE_SimulatedProxy
The actor is controlled by other client or the server it self.
ROLE_None
The Actor is not replicated.

HasAuthority() can be used to see if we are running in the server.
IsLocallyControlled() tells us if we are in control of a pawn or not.
GetLocalRole() can also be use to see if an actor/component is own/controlled by a client (ROLE_AutonomousProxy).

Recap

  • Most of the time you should try to solve most of the sharing data only with Replication.
  • Try to run most of the gameplay rules over the server.
  • Use the information from the server to reconstruct most of the gameplay over the clients (see whats the bare minimum amount of data/variables you can get away with).
  • The Engine comes with a lot of things already done for us, like the already replicated Character/Vehicle/Projectile classes (for example). That’s not for say that you should only do FPS or games similar to fortnite, but you can see what can be reuse (like using the character pawn to represent an NES game top down vehicle for example). Try to see what can you come up with.

The network replication with unreal even with so much features, Epic has to offer a really good set of mechanisms to share data from server to clients without to much trouble.
But unfortunatly, we are going to need to send some data and events from the clients to the server, for that, we can use RPCs. I will write more about them in my next entry.

Share on

Jesús Mastache Caballero
WRITTEN BY
Jesús Mastache Caballero
Game Developer