Proper architecture for updating a UI in a lobby system

Allow me to run a little scenario for you…
My project has a blank “LobbyMap” containing the following setup:

  • LobbyGM (AGameMode)
  • LobbyGS (AGameState)
  • LobbyPS (APlayerState)
  • LobbyPC (APlayerController)
  • LobbyWidget (Full screen container widget, with a “Ready To Play” button at the bottom)
  • PlayerEntryWidget (Template widget for displaying a player’s name, avatar, ready state, etc)

So “Bob” runs the standalone game, and chooses “Host” from the main menu. This creates a session (via Steam OSS) and loads the lobby map for Bob, who is now the listen server.

Client-side things that should happen for Bob:

  • Create & display an instance of LobbyWidget
  • Populate Bob’s LobbyWidget with a single instance of PlayerEntryWidget, which reflects Bob’s player info

Then “John” runs the game, and chooses “Join” from the main menu. He is presented with a session search result dialog, and can see Bob’s session.
John joins Bob’s session, which automatically loads the lobby map for him as a client. Bob receives a login notification.

Client-side things that should happen for John:

  • Create & display an instance of LobbyWidget for John
  • A new PlayerEntryWidget should be created reflecting John’s player info

Now comes the fun part… How do I update both Bob AND John’s UIs to reflect the fact that both players exist in the lobby?
And then, if John presses the “Ready To Play” button, how should this be communicated so that both Bob, John, and all future logins know that John is ready?
Which RPCs should be used, and where?

NOTE: I already understand the basics of working with UMG in both C++ and BPs, as well as all the session hosting/joining stuff.
I’m mostly concerned about where my data should be kept, how it should be referenced, and how to properly replicate that data in a way that ALL players UI’s can clearly see

I think what you want is the YourGameInstance

The GameMode for functions to count joined players, GameState for more general functions like assigning IDs.

Well, the Network Compendium doesn’t actually state the use of AGameInstance anywhere. My guess is that it has nothing to do with networking, and only exists client-side.
It would probably be something I’d use to persist data during a server travel, I guess? But not so much a place to store Player/UI data?

AGameMode only exists server-side, so clients can’t access it directly.
AGameState exists on both client and server, but I’ve had trouble accessing it from clients.
APlayerState is replicated to all clients, and each APlayerController owns one, but (AFAIK) you can’t access the UI from APlayerState

So if I made a struct like this:



USTRUCT(BlueprintType)
struct FLobbyPlayerInfo
{
	GENERATED_BODY()

public:
	UPROPERTY(BlueprintReadWrite)
	FString PlayerName;
	UPROPERTY(BlueprintReadWrite)
	FUniqueNetIdRepl PlayerId;
	UPROPERTY(BlueprintReadWrite)
	bool PlayerReady;
	UPROPERTY(BlueprintReadWrite)
	UTexture2D *PlayerAvatar;
};


Where could I store an array of these, where the server has authority over them BUT ALSO clients can request changes to them from their UIs?

Just noticed that you posted in C++, i currently work on setting this up myself, but with blueprints.

For blueprint I plan to use a combination of this example (taken from the Advanced Social System marketplace pack), maybe it gives you an idea.