One of the biggest problems when getting into UE is that the documentation is very lacking in some areas. One example, is that they talk about their framework, but I didn't find anywhere is how this framework is organised between Server and Clients.
This post is meant to shed some light on how things are structured, so that you can get a better understanding on how things work and what exists where.
This post is meant to shed some light on how things are structured, so that you can get a better understanding on how things work and what exists where.
NETWORK IN UNREAL
Unreal's network is the standard
server-client architecture. Basically, the
server is authoritative, and the clients send information to the server, which the server then validates and executes upon.
So when you're moving your character, the one that actually moves it is the server. You can specifically see this if you have a bad connection with the server, where you'll feel the character unresponsive and your character position will be corrected, warping it to where it actually is in the server.
This also means that clients never talk to each other directly. If you want to send a chat message to the players on your team, what you're actually be doing is sending a message to the server saying that you want to send a message to your team, and the server will be the one relaying it.
When developing a game that you want to work in multi-player, I advise you to always keep this in the back of your head, never just "do something", tell the server to do it (exception being client only things, that should just be "visual stuff", nothing that actually influences the game).
So when you're moving your character, the one that actually moves it is the server. You can specifically see this if you have a bad connection with the server, where you'll feel the character unresponsive and your character position will be corrected, warping it to where it actually is in the server.
This also means that clients never talk to each other directly. If you want to send a chat message to the players on your team, what you're actually be doing is sending a message to the server saying that you want to send a message to your team, and the server will be the one relaying it.
When developing a game that you want to work in multi-player, I advise you to always keep this in the back of your head, never just "do something", tell the server to do it (exception being client only things, that should just be "visual stuff", nothing that actually influences the game).
FRAMEWORK & NETWORK
So given this, it means that the framework is laid out between:
The next picture shows how the objects would be distributed through the network:
Notice the intersection between client 1 and 2 doesn't have any objects, just like I mentioned above, everything goes through the server.
The Game Mode (class AGameMode) is only meant to define rules of the game, for example how many lives each player starts with, check for winning conditions, etc. It is only present in the server, so you want to only handle there things that only the server would care about.
The Game State (AGameState) is probably the most important globally shared class. It holds a list of the players in the game (Player States), so when you want to get a player you go through it, NOT through UGameplayStatics::GetPlayerController (which is a very common beginner's mistake).
So if Game Mode held how much time a round of the game took, the Game State can be seen as the class that would keep track of the time remaining.
So if Game Mode held how much time a round of the game took, the Game State can be seen as the class that would keep track of the time remaining.
The Player State (APlayerState) is the most important player related class, because it
represents the player, and as such is where the important information about the player will be kept (e.g. how many lives he still has, team he belongs to, username, etc).
The Pawn (APawn) is a thing that the player can control (through the Player Controller).
There can be multiple Pawns in the game, however the Player Controller can only possess one at a time.
For convenience, UE has a Character (ACharacter), which comes from Pawn, and adds a "network movement component", which handles the movement of the Character. Like I mentioned above, the server is the one that moves things, not the client, so it is because of that "special" character movement component that we're able to just say locally to move the character, but in fact that abstracts for us the fact that the data is being sent to the server to act upon it.
There can be multiple Pawns in the game, however the Player Controller can only possess one at a time.
For convenience, UE has a Character (ACharacter), which comes from Pawn, and adds a "network movement component", which handles the movement of the Character. Like I mentioned above, the server is the one that moves things, not the client, so it is because of that "special" character movement component that we're able to just say locally to move the character, but in fact that abstracts for us the fact that the data is being sent to the server to act upon it.
The Player Controller (APlayerController) is in my opinion the biggest trap for newcomers to UE
.
Most people associate the Player Controller with the representation of the player, which is wrong. The Player Controller can be seen as the "player high level input".
Basically when the player possesses a Pawn, this is the class that will control it. The reason that I call it high level input and not just input, is because you CAN have the input in the Pawn; in fact, I recommend you do your input in the Pawn, because in a lot of cases you possess pawns with completely different input and behaviour (e.g. a human and a car), so it is much easier to handle the input in the Pawn it refers to, than globally handle all input in the Player Controller.
By the way, the way input works, it will first be passed to the Player Controller, and if it doesn't get used up by it, it falls through to the Pawn. So you can have different levels of input, for example handling menus in the Player Controller, and then the movement of the Character itself on it.
Something that a lot of people stumble upon is how to get their Player Controller. Although it isn't easier to find, there's a rule that states that when you call UGameplayStatics::GetPlayerController( 0 ) it always returns your Player Controller.
So if you're running a server, GetPlayerController( 0 ) returns the Player Controller of the server. If you're running a client, GetPlayerController( 0 ) returns the Player Controller of that client (remember that clients only know their Player Controller, so they can't access any other).
If you're running a dedicated server (i.e. pure server without a local client), then GetPlayerController( 0 ) will return the first client.
Most people associate the Player Controller with the representation of the player, which is wrong. The Player Controller can be seen as the "player high level input".
Basically when the player possesses a Pawn, this is the class that will control it. The reason that I call it high level input and not just input, is because you CAN have the input in the Pawn; in fact, I recommend you do your input in the Pawn, because in a lot of cases you possess pawns with completely different input and behaviour (e.g. a human and a car), so it is much easier to handle the input in the Pawn it refers to, than globally handle all input in the Player Controller.
By the way, the way input works, it will first be passed to the Player Controller, and if it doesn't get used up by it, it falls through to the Pawn. So you can have different levels of input, for example handling menus in the Player Controller, and then the movement of the Character itself on it.
Something that a lot of people stumble upon is how to get their Player Controller. Although it isn't easier to find, there's a rule that states that when you call UGameplayStatics::GetPlayerController( 0 ) it always returns your Player Controller.
So if you're running a server, GetPlayerController( 0 ) returns the Player Controller of the server. If you're running a client, GetPlayerController( 0 ) returns the Player Controller of that client (remember that clients only know their Player Controller, so they can't access any other).
If you're running a dedicated server (i.e. pure server without a local client), then GetPlayerController( 0 ) will return the first client.
The HUD (AHUD) is an object that is automatically spawned per player, and added to their Player Controller. Although you can use it for low level things (e.g. drawing text on screen), it is mostly used for debugging purposes. You can think of it as Unity's immediate mode UI.
If HUD is the immediate mode UI, the UMG is the new default UI system in UE, which has more complex elements (e.g. labels, text fields). Thankfully, the engines are getting away from scaleform (which I'm not a fan), and UMG is very similar to Unity's new UI system (specially the anchor system which I'm a fan).
As of 4.7.6, UE still has some issues when spawning the HUD at the start, so what I advise for now is that before you spawn any UMG widgets, add a delay (e.g. 0.2s) to let UE properly initialise stuff before the widgets are created.
As of 4.7.6, UE still has some issues when spawning the HUD at the start, so what I advise for now is that before you spawn any UMG widgets, add a delay (e.g. 0.2s) to let UE properly initialise stuff before the widgets are created.