How to setup GameState properties for Multiplayer game (C++)?

Hi there, what I’m currently trying to do is this:
On my GameModeBase::PreInitializeComponents (After calling super::PreInitializeComponents) I’m loading some FStructs from a DataTable, and then creating a UObject (that holds this Fstructs) saving each one in a TArray property in my GameState.

The problem is that this seems to me as a bad design on my part, since when a client logs in, it is not getting the correct TArray from the client GameState.
Could anyone point out an example of how to setup a TArray property in the GameState in a way that allows the client to get the correct GameState replication, even when the client enter’s the game after the server’s initial setup (in this case the client is way after the GameModeBase::PreInitializeComponents runs and sets up the TArray in the GameState, so there are no clients to replicate it to).

Maybe I’m looking at this in the wrong way? What other workflow could be used to setup some GameState properties (such as info from a default settings + loaded game) and have it correctly being replicated to the clients?

You may want to move your updating of game state variables to AGameModeBase::InitGameState. See if that works

Hi Natalo, thanks for the tip. But I don’t believe that it will help in this case.
I’m also updating the original post with more info on the issue, now that I’ve checked a few more things, and I believe it will make it clear if I elaborate more on the problem a bit more. But I’ll also reply here the main problem, and I don’t believe using InitGameState instead of PreInitializeComponents will help much, since both are dependent on the GameMode, which is not available on the Client side, where my problem actually resides:

The issue is in how my quests states are being handled, and used to setup extra event binding on these quest-dependent actors.
The current quests states are loaded only on the Server when the game starts, and in the GameMode::PreInitializeComponents it sets up the quests into the GameState in a replicated property. Once this is done, the rest of the actors in the game are initialized, and the quest dependent actors, will (during the actor’s begingPlay event) setup some extra event-binding based on the current quests that are loaded and available in this same GameState property, that holds the quests states. And all is ok in the server-side.

The problem I’m having is actually a Race Condition problem in the Client, in which the quest-dependent actors in the Client will try to access the replicated property in the GameState that holds the quests, but at that moment, this replicated property has not been set received by the client, so it access a nullpoint instead of the actual value of the replicated property. And I know that it is replicating properly, and that this is a race condition, because if I make the actors in the client wait a bit before trying to get the replicated property in their own GameState, it works just fine.

So I’ve in theory adding this delay fixes my problem, but it seems like a bad pattern to me, to just add a delay in the client actors code that will wait for a GameState that has all the required properties before continuing it’s own setup (in the beginPlay code).

Does anyone knows a good example of Multiplayer UE4 C++ code that loads save game data into the Game State, and have the client use this replicated GameState property to setup multiple actors’s information(event bindings) based on that?
I keep thinking that maybe there is a different workflow to archieve the same result (ie: on the client side, dynamically bind event to quest-dependent actors based on replicated properties from the GameState). Maybe it’s possible to replicate the Dynamic event binding on the quest-dependent actors that is done in the server side? And since this seems like a common issue, I would like to know if anyone has a good example of this in action, that is, no just the setup of a gamestate/gamemode, but an example that does something to solve this race condition or that uses a different flow so that it doesn’t happen.

PS: Just saw that there is no way to Edit the original post question to add this bunch of new info =/ So just leave them here in this post instead.

You may want to check if all of the variables have finished replicating by AGameModeBase::PostLogin as, in there, you could send an RPC to the connected controller telling it to initialize everything it needs.

Where are you performing this quest loading right now?

Hey @Natalo77 sorry for the long delay in the reply.
I marked your idea there as a solution because I just started implementing it, and I saw that it was working.
Still can’t say all is working because I haven’t gotten back to this project in a while, but your logic is sound and it is indeed working (for some of the Quests system stuff that I’ve managed to make work using this scheme in the meantime), so I believe that this is the way to go.

I think that previously I was trying to get the quest loading done through RPCs between the GameMode and GameState, but I’ve noted that the player controller is usually a better place to centralize these communications in a multiplayer game, so thanks a lot for the tip. So now I’m doing GameMode->PlayerController->GameState flow, using the postlogin, this way I don’t have to worry about these race conditions.