Get player name in multiplayer

Hi, I need the player name saved in the game instance to appear at the top of the character.

I have a menu where I can put my name, when the player types the name it is automatically saved in the game instance (DuckDuckGame)

But when I create a server, and another player connects, i see my name on top of his player, and vice versa. How can I fix this?

(yes it’s a duck with a gun)

Game Instances only exist on their own machine.
So you may be thinking “okay, I’ll just do a Server RPC and store all the players’ names on the Server’s GameInstance.”
That might work. I haven’t tried it myself though because I’m not sure how I would figure out whose name belongs to which player, AND get them assigned to them after they connect to the server after network travel.

The way that works best to handle this depends on whether the GameMode the players all go to uses Seamless Travel to get to the gameplay level after they set their names, or not.

If using seamless travel and their names are all assigned already, then you can store the names on the PlayerState class you’re using, and override a couple of functions in that playerstate class (they’re called copyproperty and overridewith) so that they copy or override (using old and new playerstates during level travel) the variables you want to persist (or override) from one level to another.

Now, these two playerstate functions are NOT used in NON-seamless travel, so if you’re doing it that way, then when the actor you stored the name on gets spawned into the level, you have to send the information from the client to the server, have the server set it, and make sure that setting replicates to all the clients. There are lots of wrong ways to do this because of race conditions between connecting to the server, opening the level, getting spawned in, possessing the pawn, etc. so even if client A’s stuff exists for the server, client B might not have fully connected or loaded yet, and might miss the nameplate getting updated (so for replicating to the clients I highly recommend using repnotify functions).

Finally, a 3rd way: Some online subsystems, such as Steam, will set the PlayerState’s built-in playername property based on the name the player has set in Steam. I have never used Steam so I don’t know how to make this one work, but I bet it’s a lot easier than the first two I mentioned (once you have your Steam thing set up for your Unreal project, that is).

The main thing that will mess you up is those race conditions, whatever method you choose. Even with repnotifies, there are race conditions not pertaining to networking, for example bout whether the actor containing the name has been spawned yet (it turns out for example that playerstates don’t exist until a few ticks after the level beginplay fires), that you’ll have to consider.

I’m sure someone on here knows a best practice to solve those when it comes to UE4. My approaches have been trial and error so far.

I recommend you show all the code involved at every step from creating a session through joining it all the way to when you set the nameplates, and show what class those are on, and what triggers them. This will help people on here help you troubleshoot.

1 Like

This is the widget that appears on top of the player

This is the game instance to connect and host a server (I’m using Advanced Sessions Plugins)

And this is the menu widget to put the player name

Using this plugin makes creating the server very easy, the problem is just getting the player name

Thank you for the screenshots - they help a lot!

I see that you are setting the GameInstance (DuckDuckGame) → PlayerName variable from the MainMenu widget’s text entry box, and
I also see that you’re getting the name back from the GameInstance PlayerName where you stored it, and then updating the nameplate on all clients.
BUT…
You are getting the Client’s GameInstance and it’s only PlayerName variable, and you’re doing that on all the nameplates on that client.
The effect then is that every client will set all nameplates that exist on their machine, to whatever that client has stored in the one PlayerName variable on that client’s one GameInstance. Nobody will know what anyone else’s name is.
You’re having the server tell all the clients to set their nameplates, but you’re telling all the clients to set all their nameplate actors to the name that the client has set on their own GameInstance.

That’s the problem, I can’t do it because I’m dumb

I think it goes something like this: The player enters the server >>> Cast to some blueprint on the map >>> The BP level takes the names of the players in the previous BP >>> It sends the player name to the widget. However, I still don’t understand how the server will transmit to the right player, it still confuses me a lot.

I’m still going to create a color system for each player and I can’t even imagine the pain it will be

I suggest you use Options when connecting to the server.

I am not familair with the AdvancedSessions plugin. If it doesn’t expose the Open Level options then I suppose you are forced to have the Client make a RunOnServer event with the name after connecting but it is tricky to get it right this way.

  • Ensure that the RunOnServer Actor has a Net Owner before attempting to make the call and that the Owner has not been set by the Client itself but replicated from the Server.
  • Ensure that the Server is setting a replicated variable rather than using Multicast RPC’s
  • Ensure that the Client using the OnRep callback (it might get called more than once) updates every out of date widget.
1 Like

I like this answer best because it avoids those pesky race conditions I was complaining about earlier, it is probably the least confusing way to do this.

And it can work for colors too! You’re not dumb - networked multiplayer is hard. Any kind of game you make, if you want it to be network multiplayer then the game is 5 times harder to make than it would be if it was just one machine running its own code. Be patient with yourself.

I guess I haven’t been giving you very clear answers because there is more than one way to handle this problem.

@GamerP57 how do you add those options to the Open Level command, if he is using Join Session node for AdvancedSessions plugin? Doesn’t that open the server’s level on his client so that Open Level node doesn’t need to be done? Maybe I’m remembering wrong.

that’s the way I’ve been doing mine. It’s a pain though. I have to do Delay loops checking for the Owner to exist. Open Level options is a much simpler way if it can be done. Perhaps Advanced Sessions lets you set the options to pass upon joining a server’s level? I haven’t used Advanced Sessions myself, yet.

Sorry for not responding in the last few hours, but I think I’m getting close! I managed to make each player have their own name and everything be replicated on the server as it should be, but now I don’t know how to change the name in menu widget

the error when I try to set the player name from the menu: Blueprint Runtime Error: Accessed None trying to read property PlayerCharacter from function: ‘ExecuteUbergraph_MainMenu’ from node: Set PlayerName in graph: EventGraph in object: MainMenu with description: Accessed None trying to read property PlayerCharacter