We are going to create a chatbox on all clients. All steps are also explained in a video at the end. Note : When building you sometime have to go back and forth.
Step 1: Create widget FD_ChatWindow and FD_ChatText
Step 2 Add FD_ChatWindow and chatbutton in MainMenu.
Step 3 : Blueprints FD_Chatwindow You first have to make some events at the playercontroller
Step 4 : Add mainmenu in playercontroller, delete from gameinstance!
Step 5 : Gamemode
step 6 : Playercontroller
ProjectSettings > Input > add binding chat enter
Video demonstration chatbox
Extra : Adding the mainmenu through the gameinstance.
I did not like my solution, where I added the mainmenu widget in the playercontroller instead of from teh gaminstance. Ofcourse both solutions are correct, but I want to keep the menu widgets on the gameinstance. So I made the next corrections.
If you run, you will get the same result. In my opinion the second solution is more consistent with the idea to keep the menu’s on the gameinstance
So what did I learn? With focus on the dedicated server.
Replication to clients only works when it is set on the server.
Often you read the word clients, this is misleading. With characters and playercontrollers for example there is 1 server and 1 client!!. So you can not get access to all clients with a playercontroller or character.
My biggest misconception was that if you use for example the switch Has Authority , with authority you can’t get acces to the remote / client by using an custom event or the other way around. Example of how it really works
So the branch is set to client, but by using the event SetNameOnServerGI (runs on server) one gets access to the server anyway!!. Although the branch is set on client!!
Same when you set branch or switch to server, you can get access to the client by using an event which is “Runs on owning client”
A widget (menu) lives only on the client, a gamemode lives only on the server. So you need a for example a playercontroller (lives on server and client) to get a widget (menu) to communicate with a gamemode.
Probably I use reliable to often.
A menu widget can get acces to the gamestate client, but not to the gamestate server. You need to use the playercontroller (event run on server) to get something done on the server side of the gamestate from a menu widget.
If a variable is replicated and changed on the server side of the gamestate, it is visible for all clients!
To get access to player state in menu widget, you have to use the playercontroller
In the gamemode you can change the playername in playerstate.
According to documentation: The GameState exists on the server and the clients, so the server can use replicated variables on the GameState to keep all clients up-to-date on data about the game. Information that is of interest to all players and spectators, but isn’t associated with any one specific player, is ideal for GameState replication. As an example, a baseball game could replicate each team’s score and the current inning via the GameState.
According to documentation: A PlayerState will exist for every player connected to the game on both the server and the clients. This class can be used for replicated properties that all clients, not just the owning client, are interested in, such as the individual player’s current score in a free-for-all game. Like the PlayerController, they are associated with individual Pawns, and are not destroyed and respawned when the Pawn is.
For this part I will make a little game : Collecting coins. At the start there are for example 1000 coins in the bank. Each player can collected coins. When there are no coins left in the bank, the game is finished. Each client gets a message showing the coins collected by each player.
Although it looks a bit overdone for such a small game, I used gamemode, gamestate and playerstate:
Gamemode : Setting the max coins in the bank (1000)
Gamestate : Calculating collected coins by players and check if coins in bank are finished.
Playerstate : Tracking number of coins collected by player.
Playercontroller : used for connecting menu widget with gamestate and playerstate.
In the next screenshots I show the final blueprints, when building you most likely need to go back and forth.
Note: I only used the interface of gamestate and playerstate to get a reference. I should have used more functions going through the interface.
Step 3 Add Gamestate and Playerstate to you gamemode!! At first I had forgotten to do this 🙁
Step 4 Changes to the mainmenu
Step 5 GameMode
Step 6 GameState
Step 7 : PlayerState
Step 8 : Playercontroller
Most of the events in the playercontroller are necessary to connect the menu widget to the gamestate and playerstate. So they are called from the menu, to get something done in the gamestate or playerstate
Step 9 : BP_Pickup
Changes made to the existing BP_Pickup. In the first event you should add an has authority switch, to make sure coins is only set on the remote. The dedicatie server has no coins (has no graphical interface). At first I got a warning in the dedicated server log.
Step 10 : New Blueprint with cube (only one) called BP_Cube
According to documentation: The GameMode object only exists on the server. It generally stores information related to the game that clients do not need to know explicitly. For example, if a game has special rules like “rocket launchers only”, the clients may not need to know this rule, but when randomly spawning weapons around the map, the server needs to know to pick only from the “rocket launcher” category.
Step 1 : Create Gamemode, Create Interface, Create reference to Gamemode. Set your GameMode in your level.
Note : If you are following along with the different parts, you already made the gamemode at step 1 of part 6
I want to store the playerinfo of each connected player in the gamemode and want te be able to print all connected players to all clients. The GameMode knows which players are connected. The problem is that the menu (widget) lives only on the clients and the gamemode lives only on the server. So I use the PlayerController (lives on both server and client) to communicatie between menu and gamemode.
Step 2 Blueprints GameMode Add PrintConnectedPlayersGM to interface gamemode. Add Event OnpostLogin in gamemode. Create var Connected Players. Create array ConnectedPlayersInfo and fill with playerinfo of each connected controller. Add Event OnLogout. Add Event PrintConnectedPlayersGM which will print the player info on server and clients.
Note: The ConnectedPlayers array is of type : Player Controller Object references! Turns out this is not my FD_PlayerController that is why you see the Cast to FD_PlayerController node.
Note: In part 6, step 3 the PlayerInfo from the GameInstance is copied to the PlayerController.
Note: PrintConnectedPlayersPC (prints on the clients) is discussed in the next step 3. player
Step 3 : Blueprints PlayerController Event PrintConnectedPlayersPC (runs on Owning Client) prints the playerinfo of all connected players on the owning client Event RunonServerGM (Run on server) which calls the PrintConnectedPlayersGM which is defined on the GameMode
Step 4 : MainMenu Add button PrintConnectedPlayers to menu
I hit K and L on client 1. So in Client 2 there is nothing happening. And the integer is not changed on the server
Step 2 Replication is enabled, variable is set on client
Nothing changes because replication on a client does not do anything
Step 3 Replication is enabled, variable is set on server
Variable changes on Client 1 and Server, but not on Client 2. I have to hit K on client 2 to get it changed on client 2. So in this setup the variable is not changed on the other client. This because only Server and client 1 are connected through the character, when I hit the key on Client 1
When asked I asked for a reaction in Unreal Slackers, I got the following answers:
Replicated variables only update when set on server. Setting them locally will change them until the next replication consideration, where they’ll get corrected back to server value
You have two instances of that character. When you press l, you are checking that characters instance.
The variable is not global but is on each instance of thirdperson character. So it changes only for that character pawn, but it does so on both server and client. The thing is, each client is controlling a different thirdpersoncharacter with its own instance of that variable
All three views (server, client1, client2) see 2 characters. Your local input only goes to the locally controlled character.
If you want a variable that is not specific to each instance of the actor but rather is shared across the whole game session for everyone then it is better to put it in a central location like the Game State
So it turns out that you can use a “Run on owning client” event together with a “run on server” event!
Video discussing the result.
So actually I am not 100% happy with the result. I want the server to know the name of the client and the health should be printed at the client.
Step 5 Make save namefunction on Interface and on Gameinstance
According to documentation : One PlayerController exists on each client per player on that machine. These are replicated between the server and the associated client, but are not replicated to other clients, resulting in the server having PlayerControllers for every player, but local clients having only the PlayerControllers for their local players. PlayerControllers exist while the client is connected, and are associated with Pawns, but are not destroyed and respawned like Pawns often are. They are well-suited to communicating information between clients and servers without replicating this information to other clients, such as the server telling the client to ping its minimap in response to a game event that only that player detects.
So it is better to use the playercontroller instead of the character for accessing client and server?
Step 1 : Create Playercontroller, create interface and create reference to Playercontroller. Note: Actually I also created the gamemode (see Part 7). I set the new gamemode for my level. So also as step 1 als take a look at step 1 of part 7. 🙂
Step 2 : Move blueprints from character to playercontroller
I am going to move the “Second video Part 5 extra changes” from the character to the player controller. This is just an exercise, I could argue that the best location for these Blueprints is actually the character.
So I moved the blueprints from the character to the playercontroller. I had to do some recompiling/ rebuilding. And I had to connect to Blueprints to the interface “Event Pickup Collected”. Also add the variable Healh which should be replicated.
Actually the biggest change was in the BP_Pickup. On overlap, the character (pawn) is given. It is the playercontroller of the character that you need. This can by achieved by using the Get Controller function. Also the Pickup Collected interface function had to be added.
Video result step 1 en 2
After entering the name in the menu. Get the playerinfo from the gameinstance and store it in the playercontroller on both client and server.
Step 3 Make SetplayerInfo in interface playercontroller.
According to the documentation : The GameInstance exists for the duration of the engine’s session, meaning that it is created when the engine starts up and not destroyed or replaced until the engine shuts down. A separate GameInstance exists on the server and on each client, and these instances do not communicate with each other. Because the GameInstance exists outside of the game session and is the only game structure that exists across level loads, it is a good place to store certain types of persistent data, such as lifetime player statistics (e.g. total number of games won), account information (e.g. locked/unlocked status of special items), or even a list of maps to rotate through in a competitive game like Unreal Tournament.
Step 1: Create a Blueprint GameInstance and BP Interface
Step 2: Connect Interface to Gameinstance and make Reference
Step 3 : Create Blueprint Widget and add Show MainMenu in Interface
Step 4 : Building the Widget
Step 5 : Event Show Main Menu in GameInstance
Step 6 : Open main menu from level blueprint
Videostep 1 to 6
In the following video I forgot to show that in Project Settings, Maps en Modes, the Game Instance class is set to your created Gameinstance!!
Previous steps are preparation for the real thing 🙂
Step 7 Create PlayerInfo Struct, Add to Interface, Store in GameInstance
Step 8 Store to PlayerInfo in Menu. Event M to print PlayerInfo
Video step 7 and 8
Wrap up Part 4
I have added another part, where on the Gameinstance al list of numbers is stored. This list is filled by the clients. In this case I used the character for getting access to the gameinstance of the server
Note: In the documentation the blueprints are changed with the different steps. I am building new versions each time:
Space bar = MulticastSpawn p = Run on Server o = Run on owning client
Note: In this example the blueprints ar build in the character. The character lives both on the server and the client. So that is why, a function can by activated on the server by an action on the client.
From the documentation: Pawns (including Characters) will also exist on the server and on all clients, and can contain replicated variables and events. The decision of whether to use the PlayerController, the PlayerState, or the Pawn for a certain variable or event will depend on the situation, but the main thing to keep in mind is that the PlayerController and PlayerState will persist as long as the owning player stays connected to the game and the game doesn’t load a new level, whereas a Pawn may not. For example, if a Pawn dies during gameplay, it will usually be destroyed and replaced with a new Pawn, while the PlayerController and PlayerState will continue to exist and will be associated with the new Pawn once it finishes spawning. The Pawn’s health, therefore, would be stored on the Pawn itself, since that is specific to the actual instance of the Pawn and should be reset when the Pawn is replaced with a new one.
So it is better to use Playercontroller?
Step 1 Multicast (Spacebar)
The multicast only spawns to the clients if it is activated on the server. So on a dedicated server how to activate this function?
Step 2 Run on Server (key p)
Works on the Dedicated Server (local). Important that spawn actor is set on replication!
Run on Server in combination with replicate is an important option with dedicated server, because you only have acces to client. From the documentation: The core of the networking technology in UE4 is actor replication. An actor with its “Replicates” flag set to true will automatically be synchronized from the server to clients who are connected to that server. An important point to understand is that actors are only replicated from the server to the clients – it’s not possible to have an actor replicate from a client to the server. Of course, clients still need to be able to send data to the server, and they do this through replicated “Run on server” events.
Stap 3 Run On Owning Client (key o to print inventory)
Explanation in my own words;
Character lives on both client and server
Variable Inventory lives on the character, so is accessible on both server and client
Triggerbox is in the level.
The character enters the triggerbox.
In the code (switch Authority) the events Add Item and Remove Item is only activated on the server. That is why when using a dedicated server the print string (in events Add Item and Remove Item) does not show. With a dedicated server only the clients have an graphical Interface.
I tried to get the Inventory printed on the client, from the level blueprint of the level. This by connecting a print event to the Remote pin of switch has Authority.
Text is printed on all clients. And it is the wrong text. So it looks like all clients are connected to the remote pin on the switch. Although it is a specific character which enters the triggerbox? To be continued.