Replicating players' names/custom colors

I’m making a project loosely based on the Blueprint Multiplayer project on youtube (except it’s a PhysicsBall project with some edits). I’m trying to do something the series doesn’t do: Replicating properties of the Pawn (PhysicsBall) in a multiplayer game. (The series uses entirely different classes of character for character select so I can’t reuse that code).

(I’ve since found out some things, like that GameMode is server-only and PlayerControllers only exist for their respective players and the server, which the tutorial didn’t mention.)

What I want to do is have players select a color and material in their own options menu, then send that information to the server and replicate it. I’m currently using the tutorial’s PlayerInfo struct for this, stored as a member of the LobbyController class (PlayerController subclass).

After players connect to a lobby, the LobbyGameMode adds them to the list of PlayerControllers, spawns them in, then updates everyone with the new player list:

The respawn event:

The event that updates everyone with the player list: I have arrays of PlayerControllers, Pawns and PlayerInfo structs. This event clears/reconstructs the Pawns and Playerinfos arrays, then sends all three out to each PlayerController (yes, I know not all the PlayerControllers will be there on clients. I mostly don’t use them.) The PlayerInfos are definitely all valid and correct, since the menu gets the names from them.

This event in the LobbyController class updates the list of players in the LobbyMenu, then sets players’ materials and names: (Nothing I’m doing here needs the PlayerController array so that’s not the issue- I only use it in the menu to see which player in the list is the owning player.) There’s a cast from Pawn to PhysicsBallBP here which should always succeed (since the PhysicsBalls are spawned and possessed before the GameMode syncs all the info). It doesn’t always succeed, but this isn’t the entire problem.

These events in PhysicsBallBP actually set the names and materials/colors from the given PlayerInfo: It runs on the owning client, since everyone is doing this separately from their PlayerController. This is where it gets weird:

  • Clients can only see their own names until someone else connects after them - then they can see everyone’s name except the one who just joined.

  • Clients can’t see anyone’s material except the server’s, and then, only when someone joins after them.

  • The server can’t see anyone’s info except their own - all names and materials are the BP default no matter how many people have joined.

In the LobbyController event, a lot of PhysicsBallBPs are null - the newest spawned one is null for everyone else, and everyone else’s are null for the newest spawned one.

I think this is two separate problems: First, maybe the balls aren’t replicated so soon after they’ve been spawned? If so, how should I be updating everyone’s data?

Secondly, even when the PhysicsBall is valid, no one’s material except the server’s gets changed anywhere. I have no idea about this since names are being sent out fine, and the material is just another field in PlayerInfo. All the actual editing of the BP, both names and materials, happens on the client for every client. Any help would be appreciated.

Learning the same thing this week, so might be mistakes, please correct if anything is wrong :slight_smile:

Replicated variables only change during level if executed from server(on server) execute on client and you can set your own but changes wont be seen by other clients, so when a client changes values, he needs to pass those values into an object that is both client and server , use a “execute on server” to update the value, now new value is accessible to be pulled out during your player array grabs.

Easiest to brake it into two,

  1. update information, pass the new information to a replicate object, in there “execute on server” set the variable there.[player state,player controller or game state] , not in game instance or widget
    (can use game instance as a carry bag between levels but will have to pass variables/struts back into a “client server” object for replications in new level)

  2. update all connected clients with either an updated client event or function, or a tick event , Tick event in widget appeals to me as it updates automatically, and can only be execute by owning client so one less thing to worry about while learning, just remember to place a delay somewhere.

  3. game state has a player array of all connected players “player states”, so storing info in player state seems a good idea.
    name in

    Bounce through player controller due to ease of getting references( and still unsure so playing it safe)
    Back the other direction updating via tick in lobby widget
    and a player state one for original player name entered in main level before travel to lobby level using game instance as persistent storage. (can also use copy-properties in player state, only just figured out correct usage, one of those once you know its obvious things :slight_smile:

the above is a basic example, the main bit to see is the flow of information from individual client to server request and how to make it accessible for your calls, hope I haven’t made any mistakes, or misled you, welcome any and all corrections.

OK, I fixed part of the issue - the LobbyController’s “Save Game Check” function (which checks for a stored name/material/color and loads it to PlayerSettings) wasn’t sending the data to the server, so all the server versions of the PlayerControllers had default PlayerInfo structs. (I thought the names were all being updated correctly because they were all the same. I’m dumb.)

this event in LobbyController fixes that particular problem (stuff I added is the stuff not commented):

This confuses me though. The “Player Settings” variable in LobbyController is set to “Replicated”. This custom event just seems like it manually replicates the PlayerSettings variable. So what is this actually doing that isn’t done by setting the variable to “Replicated”?

This hasn’t fixed my other problem: the server never updates the clients’ balls, and the newest-joined player is always default for everyone and ALSO has all-default balls until someone else joins. I’m gonna try some multicast stuff to see what happens there.

OK, I think what’s going on is I have to wait for the client to load the game settings. If the server calls “Sync All Player Info” immediately, I have the problem, but if I introduce a delay of say 0.5s, then when it finally runs it updates everyone perfectly. So I guess I need to fire an event when the client finishes loading the settings? I thought the load game/save game nodes already delayed execution but I guess calling those on the client wouldn’t delay the server.

I disconnected “Sync All Player Info” from the OnPostLogin event and moved it into the LobbyController here:

This seems to work fine except it doesn’t update the server’s own ball right after the game starts. Not sure why that’s happening, but it’s a minor problem that’s probably not hard to work out, I’ll just litter the code with print statements until I find out what’s not firing.

In my game I use on possess to call these kinds of functions so

Onpossess, set enum team number whatever my player state team info is my enum being set is a rep notify which runs sets colors etc.

easier to just use a player state to house this information to grab and set to the controller when you enter game.

Yeah, I’m changing it to use PlayerState and GameState classes now after a bit of confusion with Steam names. Just seems way more appropriate. The Blueprint Multiplayer tutorial really should be reworked IMO since the more I understand about the multiplayer architecture, the more it just seems like a pile of kludges.

OK, another problem with PlayerStates: at first, they only exist on the server, and have to be replicated to the clients before clients can use them - for a couple of ticks, they’re null. Is there an event that fires as soon as the PlayerState gets replicated? If it were a variable in any of my classes I could just use RepNotify.

If this doesn’t work I’m going to go back to using the old tutorial kludge since it is slightly faster, even if it’s not the “proper way” to do things.

before you get really far in getting this all worked out make sure your testing in a dedicated server and disconnect and reconnect a client mid game to see if it replicates right. Such as new client sees the changed skin colors and names

A must read

It will only make sense after you understand it :slight_smile:

In a client server model, unless you use dedicated server, the first client to join is the servers client, treat the servers client as you would any other client.
Set up the order of operations so everything fires in a logical order and not independently if possible, (might want to check out flow controls) decide if you are pushing or pull information, how, why and who needs to be authority.

Main menu level>lobby menu level>

In main menu if clients set values these will need to be stored or carried to the lobby level, once the lobby menu level opens those values need to be applied.
Once those values have been applied you want those values to be accessible to other clients
After they are accessible you want other clients to access this data.

IF you use [on post] you may need to use a [delay] between setting up data and clients accessing data, especially if you are getting data from saved game objects( how long does it take to retrieve from a players old hard drive? then for a client to get the order from server to retrieve it from a save game object, populate it and for that to get back to server, could be seconds) this creates a lot of unknowns you need to allow for.

Better than a delay would be setting up time line so everything fires in sequence instead of con-currently (events in a line fire off in sequence but don’t wait for completion of previous events, what ever happens in the event before it is none of his concern) you probably know this, just covering all bases, so yeah be aware of timeline and event flow control.

yes player stats are only server side but they are replicated and only the server can handle player state information. but u can still do things per player in their player state. i do this my self with player side changes in my waiting room(Lobby) when waiting for more players to connect. so u can do the whole character names ext this way. so names and color can easily be done in the same manner. i dont let players choose their own names i use the steam names or computer names (when using pie) to do these things btu i do use the player sides int his manner with a enum that tells my system which side they are on.

Also with [player state] under the Class Defaults you can increase the “Net Update Frequency”. The default is once per second which will appear slow on all clients including server client, not sure of impact on net traffic, but if it’s only a lobby can’t hurt, try at 60 :slight_smile: , might pay to check all replicated objects, (player state/player controller and game state) if you’re bouncing data through them and they are all set low could create conflicts.