GameInstance to Level to GameMode

Hello folks,

I have a question regarding the logical flow of events as they pertain to a multiplayer game. Specifically I would like to find out what is the sequence of events when a session is created / joined.

Let me first describe what I am currently doing

Server Creation:

  1. The user starts the game and initiates the creation of a server which allows them to input a handful of properties like servername, max number of players, game mode, etc
  2. Once the user triggers “create server” my custom NetworkGameSession object takes over and does the following
  3. UMG button click binding calls
  4. HostSession(Player->GetPreferredUniqueNetId(), GameSessionName, ServerName, bIsLAN, bIsPresence, MaxNumPlayers, bIsPasswordProtected, SessionPassword);
  5. This in turn calls
  6. bool bCreateSession = Sessions->CreateSession(*UserId, SessionName, *SessionSettings);
  7. The outcome of CreateSession triggers my OnCreateSessionCompleteDelegate
  8. void UNWGameInstance::OnCreateSessionComplete(FName SessionName, bool bWasSuccessful)
  9. The outcome of the OnCreateSessionCompleteDelegate triggers OnStartSessionCompleteDelegate
  10. void UNWGameInstance::OnStartSessionComplete(FName SessionName, bool bWasSuccessful)
  11. This finally ( if successful ) handles the opening of a Lobby level and the transition of the player to said level
  12. UGameplayStatics::OpenLevel((), FName(*FString("Lobby")), true, "listen");

Client Joining:

  1. Going to skip the finding of the servers but needless to say there is a server browser that lists the games of which a user can select one and proceed to join that server
  2. The server selection triggers the following Join call
  3. JoinASession(Player->GetPreferredUniqueNetId(), GameSessionName, SearchResult);
  4. Which in turn has the following callback if successful OnJoinSessionCompleteDelegate
  5. void UNWGameInstance::OnJoinSessionComplete(FName SessionName, EOnJoinSessionCompleteResult::Type Result)
  6. Which again if successful triggers the joining of said server and the travel to the correct Lobby map
  7. PlayerController->ClientTravel(TravelURL, ETravelType::TRAVEL_Absolute);

So now at this point I have two players 1 of which is the server sitting in the same map and they can see each other.

Now my issue is that the Lobby level has a custom LobbyGameMode associated with it

class TESTMPGAME_API ALobbyGameMode : public AGameModeBase

Inside of the game mode I have the following methods over written


	* Initialize the game.
	* The GameMode's InitGame() event is called before any other functions (including PreInitializeComponents() )
	* and is used by the GameMode to initialize parameters and spawn its helper classes.
	* @warning: this is called before actors' PreInitializeComponents.
	virtual void InitGame(const FString& MapName, const FString& Options, FString& ErrorMessage) override;

	/** start match, or let player enter, immediately */
	virtual void BeginPlay() override;

	virtual APawn* SpawnDefaultPawnFor_Implementation(AController* NewPlayer, class AActor* StartSpot) override;

	virtual void PostLogin(APlayerController* NewPlayer) override;

	virtual void GenericPlayerInitialization(AController* Controller) override;

	virtual void InitSeamlessTravelPlayer(AController* NewController) override;

	virtual void StartPlay() override;

	void HandleSeamlessTravelPlayer(AController *& C) override;

	void HandleStartingNewPlayer(APlayerController * NewPlayer);

	virtual FString InitNewPlayer
		APlayerController * NewPlayerController,
		const FUniqueNetIdRepl & UniqueId,
		const FString & Options,
		const FString & Portal
	) override;

	virtual void PreLogin
		const FString & Options,
		const FString & Address,
		const FUniqueNetIdRepl & UniqueId,
		FString & ErrorMessage
	) override;

Now with all this in place, none of my GameMode functions are being called. I haven’t implemented them yet so all I am doing is just printing the method name as the Player would be accessing it. Example)

void ALobbyGameMode::HandleSeamlessTravelPlayer(AController *& C)

But again nothing gets printed to screen and it appears like none of the GameMode functions that should be called are being initalized

Further to that I also have a MainMenuGameMode and that one, for example, has PostLogin overwritten and gets called when the game starts up. I presume this is because a default GameInstance is being created and UE4 is just going through the motions of creating a baby server.

Both my MainMenu and Lobby level are created the same way where I have a Level Blueprint and a Level C++ class that overwrites the default behaviour. Also each level specifies their own custom game modes.

What I can see is when the players join and I try to print out which GameMode is being used I can see that it’s correctly setting up my LobbyGameMode just not initiating any of the functions one would expect to be triggered.

I thought perhaps the reason was becase I was trying to do OpenLevel instead of another travel method but when I switched my logic to


The same result comes up where nothing on my LobbyGameMode is triggered.

Looking for advice how I can make this behave as expected.

My suspicion is that when the new Level is loaded the GameMode is not re-initialized but rather attached to the Level. Which makes me think I either need to trigger the re-initialization or there is a parameter somewhere I am not passing to either OpenLevel or ServerTravel.

The reason I need to get at the GameMode methods is pretty straight forward, I wanted to intercept Pre and PostLogin calls such that I can manipulate the PlayerController accordingly from changing the HUD to loading the appropriate user settings, etc etc

I appreciate any advice you guys can provide, Thanks.

So you use level steaming between main menu and lobby?

In the spirit of not leaving questions hanging I finally found my solution. Basically somewhere between UE4 crashing my changes to the BP_LobbyGameMode blueprint my LobbyGameMode class was not saved as a parent.

Hence nothing was being called but after this little, yet frustrating, correction everything started working as expected.