How to replicate to late joiners in a session?

Hello, I created a character editor for my game but when I join a session the joining player does not see the current players skeletal mesh or materials. The players already in the session on the other hand see everything.

They way that I currently have this working is when the created player is completed the game goes to the main menu where all the players features are stored on the owning controller. This is skin color, skeletal mesh, hair, Eye color, etc. When the player joins a session. On BeginPlay for the pawn will set all the characters feature values for that pawn from the owning controller.

I do this by taking the gender from the owning controller and triggering a RepNotify based on their gender boolean (should set features for they w/ rep notify). Then updating the features within the notify function. All variables are replicated as well.

I tried the generic replication in which the multicast custom event calls the set features function and the custom event on server function calls the multicast function but this does not work either.

I can tell the replication is working a little because if the player is already in the session they can see everyone elses features.

Does anyone know what I can do now to make it so the players currently in the game can rebroadcast their features?

I tried to take all the player controllers from onPostLogin from gamemode and have them rebuild themselves by calling the set features function again. No success…

I am currently trying to call the set features function from the private pawn in PlayerState. But also no dice.

I AM STUCK :smiling_face_with_tear:

help please

I also have even stuck with this late joiner replication but now I finally solve(but maybe there are side effects for other mechanic)

Here are little tips of mine

1.If you replicate variable from the widget have you pluged self player controller to owning slot when you create widget? Because it is important when you want to replicate to server that required owning client.

2.Have you pluged your variable from event to event untill reach your setting mechanics?

3.Have you learn that some nodes can’t be excuted for specific replicate? like spawn actor, possesses , apply damage …etc these nodes only for run on server.

4.Where do your character mechanic store? For me actor component with replicated in my character is stable for store them.

Hope my tips will help.

1 Like

Thank you for your response. I will follow some of your guidelines when I work on my project tonight. I think my biggest confusion is that it is replicating for people already in the map. Which means the way I am replicating should be right. But there has to be a way to refresh all players when a new player joins.

Everyone is saying repnotify handles this but its not working for me. I will debug later tonight.

I did read something that said the player controller feom server does not replicate to clients. But this in my case is false. Client or server if you are in the session you can see everyones features. If you sre new to the session you only see your own features.

You should use a Rep_notify based system for the changes.

Changes to the Pawns skeletal mesh should happen on the Owning client first, then RPC the server to update. The server in turn calls a multicast → Sets Rep_Notify variable (preferably a struct).

The OnRep function Needs to exclude the Autonomous local client from executing. You should use Local and Network Roles for flow control. Only the SERVER and Simulated Proxies should execute the rep function update process.

The only other thing I can suggest off the top of my head is to Flush Net Dormancy. This forces dormant actor to replicate but doesn’t change NetDormancy state.

When the new pawn spawns it doesn’t currently have all the updates (replicated vars etc) from all “relevant” actors. Flushing forces a rebroadcast which will update the new guy.

1 Like

Ooh this maybe the way. My only issue is that I thought I was doing this already. I may be confused on how I am using rep notify. To explain what I am doing a little bit better. When BeginPlay is called on my pawn. The owning controller takes the gender. Which is already saved in a replicated variable. Once it determines the gender with a branch conditional. It goes to a repnotify boolean. This boolean triggers the OnRep_IsMale function in which I do the server side replication. I.e. I take the mesh and uodate the male features. The features here are not even unique its basically setting the skeletal mesh to a male or female tal_nrw_body. Is this not how I should handle this?

Hmm… its actually possible I am not using it right. The boolean that calls repnotify does not change anything. I have a struct in game instance that has all the values I need. Maybe I should find a way to call repNotify everytime I set those values to my pawn?

Update: I called onRep for each feature variable and it replicated the same features onto each player. I then tried to call the vsriable from the controlling controller and it doesnt replicate everything. So still stuck but moving a little

Take a look for my blueprint, You might notice for something.

1 Like

Thank you, the only thing that truly looks different is how you are handling controller on gamemode. I am not doing anythinf like this.

I will try to do somrthing similar when I have the time

Replication only works “Server → Client”. Setting a value on the local client will not replicate to the server, nor any other player. Values have to be “Set” on the server for any replication to happen.

Pass the values to the server via RPC (Run on Server). Let the server “Set” them.

The RPC should come from the PAWN (character class), so it is executed on the Authoritative Pawn Proxy.

2 Likes

@Rev0verDrive Oooh, yes that makes tons of sense. I am not thinking about this the right way. If I was building this is c++ or java. The code itself will be written in the server side project. Which means the properties etc would go there as well. Here I need to have them sent to the server and set. This maybe a simple send to server situation. Let me try to move things over.

Thank you so much!

Actually I do have a question though. I initially set this to run on server as well as multicast to all clients. Shouldnt this have worked? What I did was on beginPlay call server set player features ( on server) this function then called client set player features (multicast) and this function called and set all the variables.

Some of it would work, but not all.

Begin play executes when the Pawn is spawned (Created). Possession takes place after that. Times for these varies. It’s not reliable.

All pawns are not created at the same time, nor possessed. If they aren’t created and possessed then multicast data isn’t implemented.

Skeletal meshes do not replicate. You can tick replicates, spam multicasts etc until you’re blue in the face, but they will never replicate over the network.

Rep_Notify variables is the way to go here. Rep_notify on a struct is what I use for skeletal mesh changes (cosmetics). I send enums, bools, ints for various struct members.

I pull cosmetic values from a player config (local player) and Pass those values to a Server RPC.

The Server Sets a Rep_Notify Struct (CharacterCosmetics). The Setting of that variable fires the OnRep_CharacterCosmetics function. That struct is now replicated to all connected clients.

The OnRep_CharacterCosmetics function applies the changes directly.

When connected clients receive the struct the OnRep_CharacterCosmetics function fires on their client.

New joins should eventually get an update for the CharacterCosmetics variable from every currently connected player. Yet this depends on the Relevancy & Priority of those players.

Netcull distance is very important in this regard as with NetDormancy settings on the character (Class Defaults → Replication). The default netcull distance is 150m. Outside that distance there’s no relevance unless “Always relevant” is applied to the overlapping actor.

NetDormancy for characters should be set to “AWAKE”.

If all these are set correctly and rep_notified variables are not replicating you then need to execute a Flush.

Before going that route you should debug your onRep functions to print a string as their first order of business.

1 Like

This is all extremely helpful information @Rev0verDrive once again thank you so much for this. I think I am getting close to this solution but like you said this may all depend. This is actually all going to be apart of my fallback. I will eventually be making this into an mmo server. In which I save player position and appearance data. That way maybe more simple than doing it this way haha. But I want to set it up this way first. May I ask when you say you receive the player cosmetic from a player config. Is the congue coming from the local player pawn? How I have it working is that the player is created. Then the players features is stored in a struct that is saved in the game instance. When the game starts I set the features on begin play as explained earlier. Is my struct essentially the same as how you are setting your local player cosmetics? If thats the case I think I may almost be on par with how you are explaining things. I will have to add the run on server again but beyond that I can probably step through with debugging to see whats happening. Also, when you set the struct on server are you also setting the values to the pawn here? You did say the OnRep_CharacterCosmetics function applies the changes directly. So I am assuming inside the function you set the features? Which means I did this partly right haha. I have little children so I usually only get about 2 hours from 12 to 2 a.m. :sweat_smile: so once again you are a life saver!

My general setup (config) is simply using a Data Table.

The Production side will be pulling data from a remote backend server where player stats etc are stored. Using a custom secure API. The Gamemode would request the data via OnPostLogin event. Server would then spawn the pawn, set the rep_notify struct and then have the controller possess.

My game also allows for players to swap clothing/gear/weapons etc in real-time as they play. Remove, change etc.


OnRep_notify variables replicate (server → client) when their values change.
OnRep Functions execute when their bound variable is updated.

Base CharacterCosmetics struct is similar to…

  • Gender: enum ()
  • Skin Tone: enum ()
  • Clothing: Struct {slot1(string), slot2(string), slot3(string), slot4(string), etc}

When you change a struct member only the changed member/value is replicated. Not the entire struct… just an FYI.

And Yes, my OnRep_CharacterCosmetics function uses the values and applies the changes.

1 Like

Ahh I see so fairly similar. Im not sure if I have to change any struct members within the game. I my characters are sent to playfab and a backup of their festures are saved to a local save slot. Still this is very helpful… I will try to do something tonight or tomorrow. If it works Inwill mark your explanation as the solution else Inwill send you some screen shots if thats okay

1 Like

Alright so what is happening is that everything is kind of replicating except for the skeletal mesh for the server on the joining client. Is this what you explained earlier? Their face is replicating though
I thought that calling repnotify resolved the skeletal mesh issue? Obviously I maybe missing something.

(Also please ignore the extra embedded rep notifies, unless this is causing my error?) I was going to clean them up later

Also, is it an issue that im setting my struct in the game instance? Im not sure where else I cN save it at.


Rep_notify does solve the issue. Yet you are trying to “replicate” a skeletal mesh component. Those will not replicate.

Replicate an int, enum, string, or fname that represents the component.

e.g. an Fname for a row in a data table. Then look that row up to get the skeletal mesh component, then apply it.

Okay you said this, I just didnt fully understand. Alright. I will store the meshes in a data table and try and retrieve them. Thanks again and again!

To be clear am I able to replicate an int value lets say 1. Then inside the rep notify, i put a switch statement that will set the values based on if 1 use skeletal mesh male? Or do I have to retreive the row from a datatable. @Rev0verDrive

Here’s a quick demo showing how Rep_notify variables work.

In construction script I create two DMI’s for the characters materials.

I create a Linear Color variable

image

In the Event Graph I set up an input so the player can hit a key to have the server change the characters skin color.

For the OnRep Function we simply “Apply” the new value.


Video demo showing it in action.

1 Like

@Rev0verDrive This is helpful, I can clean up a few ways that I implemented it on my end.

But when it comes to setting the skeletal mesh itself. Im a little confused on why solving the issue would be to replicate another value that calls the skeletal mesh.

Im dealing with many morph targets so I only need to set a specific skeletal mesh either male, female, or random.

So once the gender is determined you are saying I need to set a value lets say an int called genderBody. This int will set 0,1, or 2. Then inside of its repNotify. Can I have a switch that then sets the value based on if its 0,1, or 2? If 0 then set malebody. Just like I showed on my previous screenshot. Or must it come feom a data table?. I guess I just dont get why it would matter haha.

I have not tried this but I am confident this is the solution btw so I will mark it even though I still have questions haha

Server sets Account Character (rep_notify struct) values… e.g. Gender = Male

As soon as the Cosmetic variable is set the onRep function is going to fire (both on server and clients when they receive the updated struct).

On rep function: Cosmetics → Break struct … get the gender string → If Male set the skeletal mesh component (m_tal_nrw_body)… proceed with process.

In a nutshell each instance of the character is applying the changes via its copy of the struct and the onrep function.

Oh and I would definitely be making heavy use of the Sequence Node.
e.g. OnRep Function → Sequence…
Then 0 define the sk mesh component
Then 1 do another definition
Then 2 … something else

1 Like