Even though the network is a well covered subject in UE4 documentation, a small tutorial explaining how to get started with a really simple application is really missing. In this article, I propose you to implement a multiplayer small game over the network, and we will see how easy it is using Unreal Engine if we know where the things must be placed and what configuration must be done.
But first, let’s start with the basic principles of Unreal Engine network.
Note: if you are looking for an excellent reference about UE4 network, you need to check this http://cedric-neukirchen.net/2017/02/14/multiplayer-network-compendium/.
UE4 Networking Concepts
These are the things to know before starting. We always want to start coding but some knowledge about the concepts used in UE4 networking is mandatory to avoid losing time later.
First of all, the UE4 multiplayer is based around the client-server model. We won’t go into the details here (they can be found there), right now we just need to know that there is a Server side and a Client side.
The server side will be in charge of managing all the rules of the game, while the client side will be in charge of managing the player inputs. The connection between both will be mostly managed by the UE4 framework. Knowing this rule is important to know where all the data must be placed and managed: for instance, the score is typically something we will want to manage on the server side, meaning it will be stored by the server (replicated to the clients) and updated by the server. A client should not be able to directly update the score: it will tell the server “this player has done this action”, and the server will handle the action and eventually update the score.
The important classes for the server, the ones which will be storing the state of the game and manage it, are respectively GameState and GameMode. All the data required by the clients should be stored in the GameState.
The important classes for the client are:
- PlayerState: Contains all the attributes of a player that need to be known to every player, but which are not critical for the game. It can be the name of the player, its best score, and so on. But we won’t store the player position in this class.
- PlayerController: The interface between the human player and the Pawn.
- Pawn: The most important class, it will be the representation of the player in the game, will react to the input of the player and its attributes will be replicated to the server and all other players.
Then, this is what will basically happen on player connection on the server side: the GameMode will receive an event with the connection of the player (the PlayerController will be a parameter of the event), the GameMode will then spawn a Pawn, and will affect the Pawn to PlayerController (the PlayerController will possess the newly created Pawn). After this, the player on the client side will be able to control the Pawn created by the server.
Finally, the last important thing to know is that if we want something to be replicated to all the players, it must be marked as Replicated and it must be run on the server side.
According to this, the next steps to implement our multiplayer game are just:
– Defining the Pawn that will be controlled by the client
– Handling the connection of the players and giving them Pawns to control
– And test it
For this tutorial, the game we will make will be really simple: each player will control a ball which will move up when the space bar is pressed.
Implementing the Server Logic
The Pawn will be created on the server side. The GameMode will be in charge of spawning them and they will be managed by the server.
Let’s define our BP_Sphere_Pawn pawn. It’s just a sphere with a MoveUp method.
By default, a Pawn is replicated over the network, but we have to define that we want the components to be replicated.
Now, in the GameMode, we will react to the connection of a player by spawning a new SpherePawn and making the player possess it:
Here, when a new player is starting, we find the player start in the current server map, and we spawn a BP_Sphere_Pawn at this location (with the strategy Try To Adjust Location, But Always Spawn), then we make the player possess this Pawn.
Implementing the Client Logic
On the client side, we will create a PlayerController, that will call the MoveUp method of its Pawn when the space bar is pressed:
MoveUp needs to be run on the server side, because it needs to be known by all clients. That’s why we are calling it in an event with the attribute Run On Server.
Testing Network with the Editor
Everything is almost setup. We just have to select the right GameMode, and then we can just start the game with two players:
Then, when Play is clicked, two windows should show up. When the space bar is pressed in one, the associated Sphere should move in both windows. When the space bar is pressed in the other window, the other sphere should move in both windows.
The Content folder for this project can be found here: MultiSphere.
In this tutorial, we have seen the basic principles of Unreal Engine 4 network and how to set up quickly something working. If you follow the other tutorials on the net, you can now make something great.
We will continue to cover the subject of the UE4 network in the next tutorials, and we will go deeper in the explainations. If you want to know when the new articles are out, you can follow us on Twitter and Facebook.
Nice tutorial ! 🙂 Thank you for this. It is a good start to understand where the code needs to be at the beginning.
Oh!!! please continue this subject! the style of writing and level of depth are on point!
Good day. Could you please explain what the purpose of a Multicast custom event would be? In your example here, you do not use multicast and all, and your project works fine. So the question is, in which situations is multicast custom events useful, if the server events seem to already be sent down the clients anyway?
Thanks.
It makes very little sense to put those RPC’s in the Player Controller – you’re just creating an arbitrary dependency between the two classes then. The player already ‘owns’ the pawn class and can call RPC’s through it, and it responds to input already too.