Networking Overview

Setting up networked games for multiplayer.

In a multiplayer session, game state information is communicated between multiple machines over an internet connection. In case single-player game, all information store on one machine. This makes multiplayer programming inherently more complex, than programming for a single-player game. The process of sharing information between players is delicate and adds several extra steps. Unreal Engine features a robust networking framework, that powers some of the world's most popular online games, helping to streamline this process. This page provides an overview of the concepts, that drive multiplayer programming, and the tools for building network gameplay, that are at your disposal.

Plan for multiplayer early

If there is a possibility, that your project might need multiplayer features at any time, you should build all of your gameplay with multiplayer in mind from the start of the project. If your team consistently implements the extra steps for creating multiplayer, the process of building gameplay will not be much more time-consuming compared with a single-player game. In the long run, your project will be easier for your team as a whole to debug and service. Meanwhile, any gameplay programmed for multiplayer in Unreal Engine will still work in single-player.

However, refactoring a codebase, that you have already built without networking, will require you to comb through your entire project and reprogram nearly every gameplay function. Team members will need to re-learn programming best practices, that they may have taken for granted up to that point. You also will not be prepared for the technical bottlenecks, that will be introduced by network speed and stability.

Introducing networking late in a project is resource-intensive and cumbersome compared with planning for it from the outset. We therefore advise, that you should always program for multiplayer, unless you are completely certain that your project will never need multiplayer features.

The Client-Server Model

In a single-player or local multiplayer game, your game is run locally on a standalone game. Players connect input to a single computer and control everything in the game directly, including the Actors, the world, and the user interface for each player, exists on that local machine.

Local Play Example

Single-player and local multiplayer take place on only one machine.

In a network multiplayer game, Unreal Engine uses a client-server model. One computer in the network acts as a server and hosts a session of a multiplayer game, while all of the other players' computers connect to the server as clients. The server shares game state information with each connected client and provides a means for them to communicate with each other.

Network Play Example

In network multiplayer, the game takes place between a server (1) and several clients (2) that are connected to it. The server processes gameplay, and the clients show the game to users.

The server, as the host of the game, holds the one true, authoritative game state. In other words, the server is where the multiplayer game is actually happening. The clients each remote-control Pawns that they own on the server, sending procedure calls to them in order to make them perform ingame actions. However, the server does not stream visuals directly to the clients' monitors. Instead, the server replicates information about the game state to each client, telling them what Actors should exist, how those Actors should behave, and what values different variables should have. Each client then uses this information to simulate a very close approximation of what is happening on the server.

Client-Server Gameplay Example

To help illustrate how this changes gameplay programming practices, here is an example of two players in a multiplayer game. System refers to them as Player 1 and Player 2, and break down the process of having them fire projectiles at each other.

Local Gameplay

Network Gameplay

Local Play Example

Network Play Example 2

Player 1 presses an input to fire a weapon.

  • Player 1's Pawn responds to this by firing its current weapon.

  • Player 1's weapon spawns a projectile and plays any accompanying sound or visual effects.

Player 1 presses an input on their local machine to fire a weapon.

  • Player 1's local Pawn relaying the command to fire the weapon to its counterpart Pawn on the server.

  • Player 1's weapon on the server spawns a projectile.

  • The server tells each connected client to create its own copy of Player 1's projectile.

  • Player 1's weapon on the server tells each client to play the sound and visual effects associated with firing the weapon.

Player 1's projectile moves forward from the weapon.

Player 1's projectile on the server moves forward from the weapon.

  • The server tells each client to replicate the movement of Player 1's projectile as it happens, so their version of Player 1's projectile also moves.

Player 1's projectile collides with Player 2's Pawn.

  • The collision triggers a function that destroys Player 1's projectile, causes damage to Player 2's Pawn, and plays any accompanying sound and visual effects.

  • Player 2 plays an onscreen effect as a response to being damaged.

Player 1's projectile on the server collides with Player 2's Pawn.

  • The collision triggers a function that destroys Player 1's projectile on the server.

  • The server automatically tells each client to destroy their copies of Player 1's projectile.

  • The collision triggers a function that tells all clients to play the accompanying sound and visual effects for the collision.

  • Player 2's Pawn on the server takes damage from the projectile's collision.

  • Player 2's Pawn on the server tells Player 2's Client to play onscreen effects as a response to being damaged.

In the standalone game, all of these interactions take place in the same world on the same machine, so they are easy to both understand and program in literal terms. When you spawn an object, for instance, you can take for granted that all players will be able to see it.

In the network game, these interactions take place in several different worlds: one that exists on the server, one that exists on Player 1's client, one that exists on Player 2's client, and an additional world for each other client that is participating in the session. Each world on each different machine has its own copy of the Pawns, their weapons, and the projectiles that they fire. The server is where the game is actually being played, but we need to make the clients' worlds look like the same events are happening in them. It is therefore necessary to selectively send information to each client to create a visual representation of the world on the server.

This process introduces a division between essential gameplay interactions (collision, movement, damage), cosmetic effects (visual effects and sound), and private player information (HUD updates). Each of these is relevant to a specific machine or set of machines in the network. However, the process of replicating this information is not completely automatic, and you must specify what information is replicated to which machines as you program your gameplay. The main challenges are choosing what information you should replicate and how so as to both provide a consistent experience to all players, but also minimize the amount of information that you are replicating so as to use as little network bandwidth as possible.

Fundamental Networking Concepts

The sections below detail the concepts that drive network gameplay within Unreal Engine. It will give you an overview and quick reference of several of the tools that will help you in building your own multiplayer games.

Network Modes and Server Types

Network mode describes a computer's relationship to a network multiplayer session. An instance of a game can take on any of the following network modes:

Network Mode

Description

Standalone

The game is running as a server, that does not accept connections from remote clients. Any players participating in the game are strictly local players. This mode is used for single-player and local multiplayer games. It will run both server-side logic and client-side logic as appropriate for the local players.

Client

The game is running as a client, that is connected to a server in a network multiplayer session. It will not run any server-side logic.

Listen Server

The game is running as a server hosting a network multiplayer session. It accepts connections from remote clients and has local players directly on the server. This mode is often used for casual cooperative and competitive multiplayer.

Dedicated Server

The game is running as a server hosting a network multiplayer session. It accepts connections from remote clients, but has no local players, so it discards graphics, sound, input, and other player-oriented features in order to run more efficiently. This mode is often used for games requiring more persistent, secure, or large-scale multiplayer.

Listen servers are easy for users to set up spontaneously since any user with a copy of the game can both start a listen server and play on the same computer. Games that support listen servers often feature an ingame UI for starting a server or searching for servers to join. However, because the player, who is hosting a listen server, is playing on the server directly, they have and has an advantage over other players, that must use a network connection to play, which raises concerns about fairness and cheating. There is also an extra processing load associated with running as a server and supporting player-relevant systems like graphics and sound. These factors make listen servers less suitable for games in highly competitive settings or games with very high network loads associated with them, but very convenient for casual cooperative and competitive multiplayer among a small group of players.

Dedicated servers are more expensive and difficult to configure, requiring a separate computer from all of the players, that would participate in a game, complete with its own network connection. However, all players joining a dedicated server experience the game with the same type of connection, which ensures fairness. Since a dedicated server does not render graphics or perform other logic, that would only be relevant to a local player, it is also able to process gameplay and networking more efficiently. This makes dedicated servers preferable for games requiring a large number of players or games requiring a high-performing, trusted server for either security, fairness, or reliability reasons. Such games would include MMOs, competitive MOBAs, or fast-paced online shooters.

Because standalone games serve as both a server and a client, any logic created for a multiplayer game will function in single-player with no additional work.

Actor Replication

Replication is the process of reproducing game state information between different machines in a network session. If replication is set up correctly, the different machines' instances of the game become synchronized. By default, most Actors do not have replication enabled and will perform all of their functions locally. You can enable replication for Actors of a given class by setting the bReplicates variable in a C++ Actor class or the Replicates setting of an Actor Blueprint to true.

The following are the most common replication features that you will use to create networked gameplay:

Replication Feature

Description

Creation and Destruction

When an authoritative version of a replicated Actor is spawned on a server, it automatically generates remote proxies of itself on all connected clients. It will then replicate information to those remote proxies. If you destroy an authoritative Actor, it will automatically destroy its remote proxies on all connected clients.

Movement Replication

If an authoritative Actor has Replicate Movement enabled, or bReplicateMovement is set to true in C++, it will automatically replicate its Location, Rotation, and Velocity.

Variable Replication

Any variables that are designated as being replicated will automatically replicate from the authoritative actor to its remote proxies whenever their values change.

Component Replication

Actor Components replicate as part of the Actor that owns them. Any variables within the Component that are designated as being replicated will replicate, and any RPCs called within the component will behave consistently with RPCs called in the Actor class.

Remote Procedure Calls (RPCs)

RPCs are special functions that are transmitted to specific machines in a network game. No matter what machine an RPC is initially called on, its implementation will run only on the machine it is intended for. These may be designated as Server (only runs on the server), Client (only runs on the Actor's owning client), or NetMulticast (runs on every machine connected to the session, including the server).

While common use cases like creation, destruction, and movement can be handled automatically, all other gameplay features do not automatically replicate by default, even when you enable replication. You must designate exactly which variables and functions you want to replicate as is appropriate to your game. Detailed information on all of the above replication features is available in the Property Replication guide.

Several common features of Actors, Pawns, and Characters do not replicate:

  • Skeletal Mesh and Static Mesh Components

  • Materials

  • Animation Blueprints

  • Particle Systems

  • Sound Emitters

  • Physics Objects

Each of these runs separately on all clients. However, if the variables that drive these visual elements are replicated, it will ensure that all client has the same information and therefore simulates them in approximately the same way.

Network Role and Authority

An Actor's network role determines whose machine has control over the Actor during a network game. An authoritative Actor is considered to have control over that Actor's state, and will replicate information to other machines within the network multiplayer session. A remote proxy is a copy of that Actor on a remote machine, and it receives replicated information from the authoritative Actor. This is tracked by the Local Role and Remote Role variables, which can take the following values:

Network Role

Description

None

The Actor has no role in a network game and does not replicate.

Authority

The Actor is authoritative and replicates its information to remote proxies of it on other machines.

Simulated Proxy

The Actor is a remote proxy, that is controlled entirely by an authoritative Actor on another machine. Most Actors in a network game, like pickups, projectiles, or interactive objects, will appear as Simulated Proxies on remote clients.

Autonomous Proxy

The Actor is a remote proxy, that is capable of performing some functions locally, but receives corrections from an authoritative Actor. Autonomous Proxy is usually reserved for Actors under the direct control of a player, like Pawns.

The default model used by Unreal Engine is server-authoritative, meaning that the server always has authority over the game state, and information will always replicate from the server to clients. You would expect an Actor on the server to have a Local Role of Authority, and you would expect its counterparts on remote clients to have a Local Role of either Simulated or Autonomous Proxy.

For more information regarding Actors' network roles, refer to the Actor Role and Remote Role guide.

Client Ownership

Pawns in a network game are owned by a PlayerController on a specific client's machine. Any time, that Pawn calls a client-only function, it will be directed only to the owning player's machine. No matter which machine calls the function. Actors, that have their Owner variable set to a specific Pawn, belong to that Pawn's owning client by association. They also direct client-only functions to their owner's machine. You may use the IsLocallyControlled function in C++, or the Is Locally Controlled node in Blueprint, to determine whether or not an Pawn is on its owning client.

Avoid using IsLocallyControlled in a custom Pawn class's constructor, as it is possible for a Pawn not to have any Controller assigned yet during construction.

For more information about ownership, refer to our guide on Actors and their Owning Connections.

Relevance and Priority

Relevance is used to determine whether or not it is worthwhile to replicate an Actor during a multiplayer game. Actors, that are not considered relevant, are culled during replication. This saves bandwidth, so Actors, that are relevant, can replicate more efficiently. If an Actor is not owned by any players and not physically near any players, then it is not considered relevant and does not replicate. Non-relevant Actors still exist on the server and can affect the authoritative game state, but do not send information to clients until players are nearby. You can manually control relevance by overriding the IsNetRelevantFor function, and you can determine the distance at which an Actor is relevant using the NetCullDistanceSquared property.

Sometimes there is not enough bandwidth available to replicate all relevant Actors during a single frame of gameplay. Actors, therefore, have a Priority value, which determines which Actors get to replicate first. By default, Pawns and PlayerControllers have a NetPriority of 3.0, which makes them the highest-priority Actors in a game, while base Actors have a NetPriority of 1.0. The longer that an Actor goes without being replicated successfully, the higher its priority will get with each successive pass until it is replicated.

For more detailed information about Actors' relevance and priority, refer to our guide on Actor Relevancy and Priority.

Variable Replication

You can add replication to variables and object references either by using the Replicated or ReplicateUsing specifiers in their UPROPERTY macros in C++, or by designating them as Replicated in the Details Panel in Blueprint. Whenever a replicated variable's value changes on an authoritative Actor, its information is automatically sent from the authoriative Actor to the remote proxies connected to the session.

RepNotifies

You can designate a RepNotify function, that will be called in response to an Actor successfully receiving replicated information, for specific variables. RepNotifies only trigger locally, when a variable is updated, making them a low-overhead way to trigger gameplay logic in response to variable changes on an authoritative Actor. You can access this functionality by using the ReplicatedUsing specifier in a variable's UPROPERTY macro in C++, or by changing the Replication setting for the variable in Blueprint to use a RepNotify.

RepNotifies are preferable over using RPCs or replicated functions, as they can be added to variables, that you would need to replicate regardless of other gameplay functionality, saving a significant amount of bandwidth over creating additional network calls.

Remote Procedure Calls (RPCs)

Remote Procedure Calls are also referred to as replicated functions. They can be called from any machine, but will direct their implementation to happen on a specific machine that is connected to the network session. There are three types of RPCs available:

RPC Type

Description

Server

Called only on the server, that is hosting the game.

Client

Called only on the client, that owns the Actor that the function belongs to. If the Actor has no owning connection, this logic will not be executed.

NetMulticast

Called on all clients, that are connected to the server, as well as the server itself.

Events and functions in Blueprints can be given the same designations by setting their Replicates dropdown in the Details Panel to one of the three types available.

Replicated event in Blueprint

You can designate a function in C++ as being an RPC by providing either the Server, Client, or NetMulticast specificer in its UFUNCTION macro. Their implementations use the suffix _Implementation in their code implementations.

ExampleClass.h

//Declaration of Server RPC MyFunction.
UFUNCTION(Server, Reliable, WithValidation)
void MyFunction(int myInt);

ExampleClass.cpp

//Implementation of Server RPC MyFunction.
void AExampleClass::MyFunction_Implementation(int myInt)
{
    //Gameplay code goes here.
}

Once you have designated a function as an RPC, you can give it gameplay logic and call it the way, that you would with any other function. For more details regarding RPCs, refer to the Remote Procedure Calls guide.

Reliability

You must designate RPCs as being reliable or unreliable. In Blueprint, functions and events are assumed to be unreliable by default. By setting the Reliable setting in the Details Panel to true, you can designate the function as being reliable. In C++, you must add either the Reliable or Unreliable specifier to any RPC's UFUNCTION macro alongside its status as a Server, Client, or NetMulticast function.

Unreliable RPCs are not guaranteed to arrive at their intended destination, but they can be sent faster and more frequently, than reliable RPCs. They are most appropriate for functions, that are either not critical to gameplay, or that are called very frequently. As an example, Actor movement is replicated using an unreliable RPC, due to the fact that it can change every frame.

Reliable RPCs are guaranteed to arrive at their intended destination, and will remain in a queue until they are successfully received. They are most appropriate for functions, that are critical to gameplay, but that do not get called very frequently. Examples of this would include collision events, starting or ending the firing of a weapon, or spawning Actors.

Overuse of Reliable functions can result in overflowing the queue for them. This will result in forced disconnections. If you call a replicated function on a frame-by-frame basis, you should make it Unreliable. If you have a Reliable function that is bound to player input, you should limit how often the player can call that function.

Validation

The WithValidation specifier indicates, that in addition to an implementation of the function, there will also be a function, that validates the data of the incoming function call. This validation function has the same signature as the function, that it is responsible for, but it returns a boolean instead of its original return value. If it returns true, then it permits the RPC's Implementation to execute. If it returns false, then it prevents execution.

ExampleClass.cpp

//Validation of Server RPC MyFunction
bool AExampleClass::MyFunction_Validation(int myInt)
{
    /* 
        If the value of myInt is negative, we do not want to allow MyFunction_Implementation to run. 
        Therefore we only return true if myInt is greater than zero.
    */
    return myInt >= 0;      
}

Tips and Further Reading

The following are basic guidelines for implementing efficient and consistent multiplayer systems in your games.

Basic Replicated Actor Checklist

To create a replicated Actor, follow these steps:

  • Set the Actor's Replicated setting to True.

  • If the replicated Actor needs to move, set Replicates Movement to True.

  • When you spawn or destroy a replicated Actor, ensure that you do it on the server.

  • Set any variables that must be shared between machines to replicate. This usually applies to gameplay-essential variables.

  • Use Unreal Engine's pre-made Movement Components whenever possible, as they are already built for replication.

  • If you are using a server-authoritative model, make sure any new actions that the player can perform are triggered by Server functions.

Networking Tips

  • Use as few RPCs or replicated Blueprint functions as possible. If you can use a RepNotify instead, you should.

  • Use Multicast functions especially sparingly, as they create extra network traffic for each connected client in a session.

  • Server-only logic does not necessarily have to be contained in a server RPC if you can guarantee that a non-replicated function will only execute on the server.

  • Be cautious when binding Reliable RPCs to player input. Players can repeatedly press buttons very rapidly, and that will overflow the queue for Reliable RPCs. You should use some way of limiting how often players can activate these.

  • If your game calls an RPC or replicated function very often, such as on Tick, you should make it Unreliable.

  • Some functions can be recycled by calling them in response to gameplay logic, then calling them in response to a RepNotify to ensure that clients and servers have parallel execution.

  • You can check an Actor's network role to see if it is ROLE_Authority or not. This is a useful method for filtering execution in functions that activate on both server and client.

  • You can check if a Pawn is locally controlled by using the IsLocallyControlled function in C++ or the Is Locally Controlled function in Blueprint. This is useful for filtering execution based on whether it is relevant to the owning client.

  • Avoid using IsLocallyControlled in constructor scripts, as it is possible for a Pawn not to have a Controller assigned during construction.

Tutorials

For a thorough walkthrough of how to implement a simple multiplayer game using the above principles, refer to the Multiplayer Quick Start Guide.

Help shape the future of Unreal Engine documentation! Tell us how we're doing so we can serve you better.
Take our survey
Cancel