In my game, players severtravel (with seamless travel) back and forth between a lobby level and a game level. In the lobby level blueprint’s BeginPlay, I have some stuff going on that ties some items in the world to the local player controller. This is activated when I first enter the lobby level, (of note–this first travel, from the menu to the lobby, is not Seamless Travel) but when we go through to the game and then back to the lobby afterward (both trips using Seamless Travel) the same BeginPlay logic doesn’t execute. In a previous build of this game that didn’t use Seamless Travel at all, this exact setup worked fine. (I’ve been moving the build to Steam, and for some reason hard travel kicks clients there, but Seamless Travel works, so I’m switching).
So my question: Does Seamless Travel never hit the BeginPlay event? Or does it hit it once, then keep the level around somewhere in memory, in “Play”, while I’m in the game, so when we return we don’t hit Begin Play again? If I want an event that fires every time players re-enter the level, what should I look to?
EDIT:
With some additional testing and research, I’ve determined BeginPlay is in fact being hit every time I seamless travel back to the lobby. However, the logic I need to execute there is on my player controller class for the lobby level, LobbyController. I have a separate player controller class for the game level, GameController. Since I’m doing seamless travel, my players are still GameControllers when they get back to the lobby, so a cast to LobbyController is failing. Is it possible to insist on throwing out and getting a new player controller even in seamless travel?
An interesting wrinkle: players hard clienttravel from their menus to the lobby, then seamless travel together to the game. So they ARE LobbyControllers the first time through. Why then do their player controllers “refresh”
to become GameControllers when we enter the game level? It’s identical seamless travel to the call taking everyone back to the lobby–when the player controller won’t change from GameController back to LobbyController.
2ND EDIT:
With further testing, I find that I’m not hitting GameMode::PostSeamlessTravel and HandleSeamlessTravelPlayer for each player, so they’re never hitting SwapPlayerController, which would otherwise set up the new Player Controller class. If I play single player, and seamless travel from lobby to game to lobby, I hit these functions as expected, and get the desired BeginPlay results I’m looking for because I have a LobbyController when I need one. But if I play with two players, I’m not even hitting PostSeamlessTravel. Why wouldn’t I hit that with multiple players?
I noticed the call to PostSeamlessTravel is wrapped in a couple if statements:
if (bSwitchedToDefaultMap)
{
// we've now switched to the final destination, so we're done
// remember the last used URL
CurrentContext.LastURL = PendingTravelURL;
// Flag our transition as completed before we call PostSeamlessTravel. This
// allows for chaining of maps.
bTransitionInProgress = false;
UE_LOG(LogWorld, Log, TEXT("----SeamlessTravel finished------") );
AGameMode* const GameMode = LoadedWorld->GetAuthGameMode();
if (GameMode)
{
UNavigationSystem::InitializeForWorld(LoadedWorld, NavigationSystem::GameMode);
// inform the new GameMode so it can handle players that persisted
GameMode->PostSeamlessTravel();
}
// Called after post seamless travel to make sure players are setup correctly first
LoadedWorld->BeginPlay();
FCoreDelegates::PostLoadMap.Broadcast();
}
I’m currently building a Debug_Game exe to find out which if statement isn’t hitting, and will update with more when I do.