Correct use of TransitionMap and SeamlessTravel

Hi, i’m looking into implementing a lobby for a multiplayer project. I recently watched the latest (16th June) Twitch broadcast in which Josh talks about seamless travel and the use of the transition map. Would you be able to expand on this a little for me?

  • Can the map that’s due to be loaded after the TransitionMap be overridden? For example, during a map vote? Would simply calling SetSeamlessTravelMidpointPause(true) after the initial ServerTravel(UrlString), followed by another ServerTravel(UrlString) if the map vote has changed the pending map handle all this? Or would that result in the transition level being loaded again? EDIT: Reading over ‘FSeamlessTravelHandler::StartTravel’ it looks likes this case is handled (L3935)

  • Does the server still maintain all its server functionality during the TransitionMap stage? For example if a player wishes to change team or type, or are PlayerStates frozen until the SeamlessTravel is complete or does everything still work as if it was a normal game?

  • Should the TransitionMap Lobby have its own unique ‘Lobby’ GameMode? Or is their a better way of doing this?

  • Would the TransitionMap be used as the startup map when hosting a game and waiting for new player?

  • Does SeamlessTravel allow for new players to connect during the TransitionMap stage? Ideally i’d like to think during TransitionMap with SetSeamlessTravelMidpointPause(true), everything related to SeamlessTravel is on hold and it’s running a normal game. Would that be a correct way to look at it?

Some really involved but powerful questions here. We haven’t tried a lot of this since Unreal Tournament 3, but I believe your understanding is mostly correct.

Using midpoint pause at the right time should leave you in the midpoint transition map with a valid UWorld. The part that you’ll have to pay attention to is the way that AActors from the previous level get moved into the new worlds. Things like APlayerController, AGameState, and AGameMode come by default (you’ll see that in FSeamlessTravelHandler::Tick). You can keep additional AActors like the AHUD (for voting) through GetSeamlessTravelActors. RPCs should be valid and you should be able to change the final destination after your voting has finished.

As for player states and teams, I would not go creating new AActors for these (ATeamInfo, APlayerState) because the APlayerStates will be created/copied/transferred in PostSeamlessTravel()/HandleSeamlessTravelPlayer() once the final destination is reached. I seem to recall there being an issue with changing from non team based to team based games in UT3 during travel, but it has been lost to time. I would keep track of teams in an additional variable and set them up finally on the other side.

Typically the transition map is a separate map than the “entry” map. That would be because you can setup a scene in the map for visuals during loading. Additionally, if you are traveling back to the main menu, it would look like MapB → Entry → Entry and that would be bad.

As for “new players”, the engine is ticking so it would be presumed that as long as a UWorld is there you would be able to join. Look at FNetworkNotify::NotifyAcceptingConnections(), implemented by UWorld::NotifyAcceptingConnections() which is responsible for making sure the world is ready and then AGameMode::Prelogin() which would reject players on game specific preconditions (capacity, etc). Otherwise, it’s a world like any other. Well, there might be some issues I haven’t thought about, but all connected clients would be told to continue traveling and it should all work out.

Hope that’s enough to go on for now, if you get into implementation snags, let me know and we’ll see what needs doing.

p.s. After chatting here, something like voting and such would probably be simpler if you have an amount of time “post match” while still in the previous level. There are things about seamless travel that aren’t replicated, like the midpoint transition pause boolean for example. Clients are told to go from A->transition->B in the initial travel message and if you changed to map C instead, clients would have to be told of that change in your code. ServerTravel can’t be called while another is in progress.

Any new “game mode” that you want in the transition map is basically an extension of the existing AGameMode being carried over from the previous level. So it’s not a new instance of the same or other class.

Thanks for the detailed reply Josh, much appreciated! I’ll put it into practice with a few tests over the next few days and post any blockers I come across here for others to see.

I’m actually having some issues regarding this topic. When I try to go from Lobby to Game I get this error about 20 times: LogNet: NotifyAcceptingConnection: Server Lobby refused which then later drops the clients connection entirely. Any ideas what may be causing this?