Pawn is unpossessed after seamless travel

Hi everybody,

we are working on a multiplayer game with 2 teams (sheeps and wolves). If a game is won, i’m using AGameMode::RestartGame to restart the same map using seamless travel. I’m using the match state WaitingToStart as a warmup phase in which only the sheeps are allowed to spawn. I override AGameMode::HandleMatchIsWaitingToStart and respawn the sheeps using RestartPlayer().
The problem is that the sheep spawns but is unpossessed after.

If the listen server is a wolf, the pawn is unpossessed in the same server time (AGameState::GetServerWorldTimeSeconds()):

278102-serveriswolf.png

If the listen server is a sheep, the pawn is unpossessed a few hundred ms later:

278103-serverissheep.png

Though if I debug the server instance of the game and set breakpoints in HandleMatchIsWaitingToStart and OnUnpossess, i can see that first OnUnpossess is called and then HandleMatchIsWaitingToStart and everything works fine. So in debugging they are called from FSeamlessTravelHandler::Tick.

OnUnpossess:

278105-onunpossesscallstack.png

HandleMatchIsWaitingToStart:

278104-handlematchiswaitingtostartcallstack.png

Without debugging, OnUnpossess is called after HandleMatchIsWaitingToStart.

Does anyone have an idea why OnUnpossess is called after HandleMatchIsWaitingToStart or from where?

Thanks in advance!

According to Travelling in Multiplayer | Unreal Engine Documentation pawns are not marked by default to persist across seamless travel, but player controllers are.

I suspect that this is happening because the OnUnpossess is being called as part of the pawn pending a destroy on seamless travel (According to your stack).

Can you double check that you’ve marked your pawns to persist?

Thanks for your answer! I haven’t done this, because I actually don’t want the pawns to persist. From my understanding, HandleMatchIsWaitingToStart() is being called as a result of World->BeginPlay(), as you can see in the upper callstack, which is being called from FSeamlessTravelHandler. So after seamless travel, new pawns should spawn, as I’m calling RestartPlayer in the HandleMatchIsWaitingToStart() (am I wrong?). The OnUnpossess should indeed be called via PawnPendingDestroy() from EndPlay() which is also called via FSeamlessTravelHandler from the same function, but before the World->BeginPlay() (RouteEndPlay in FSeamlessTravelHandler::Tick in line 5922, World->BeginPlay in the same function in line 6187). So it does not make sense to me that while playing without debugging OnUnpossess is called AFTER the new pawn is spawned in HandleMatchIsWaitingToStart. Am I missing something?

Ok, I’m very sorry, it was my bad. I forgot to clear a timer at the round end, which was setting the state to spectating and therefore destroying the pawn. So now it is working if the server is a sheep, but not if it is a wolf. I will go through the code again for any more timers etc…

It’s finally working. My mistakes were: forgetting to clear a timer at the round end and thinking that FSeamlessTravelHandler would somehow wait until all clients are ready before the match was restarted :confused:

All good, sometimes simply asking the question helps us come to an answer ourselves. Good luck!