Seamless Travel - Unwanted actors coming across on client

Hi

We have seamless travel set up in our game but we are experiencing a problem.
At the end of our game level we are getting actors kept on our client which we no longer want when transitioning to our intermediate level.
It seems as though in FSeamlessTravelHandler::Tick will automatically keep any simulated proxy or autonomous proxy actors on the client which have been dynamically spawned by the server.

This seem down to this line: (World.cpp : 4897 in 4.12.3)

// keep if it's dynamic and has been marked or we don't control it
if (bSameLevel && (bShouldKeep || (TheActor->Role < ROLE_Authority && !bDormant && !TheActor->IsNetStartupActor())) && !TheActor->IsA(ALevelScriptActor::StaticClass()))

For example we don’t want our pawns to travel but they do because they have been spawned on the server and replicated to the clients.

Does anyone know a good way around this? I thought about creating a new ULevel at runtime and spawning them in this level on the server so that they are not in the persistent level. That seemed a bit over-complicated and wrong to me. I also thought about modifying the line above in the engine but I guessed it was in there for a good reason.

Thanks in advance,
Mark.

My first thought is that you are leaking AActors on the server. The code you highlight tells the client to leave actors alone that the server created because it’s the server’s job to clean up the actor channels. Client’s can’t go deleting these actors on its own because it would mess up / confuse the server.

This code is very old, and while it has undergone a slight refactoring for readability, the premise remains.

What kind of AActors? What are their relationship to the pawn or player controller?

Can you make sure that you don’t have something holding onto to those AActors? GetSeamlessTravelActorList() should be checked if you overloaded it, and make sure links to objects you do hold don’t hold references to actors you don’t want. Also might want to check you UGameInstance and anything it holds onto to make sure it isn’t rooting actors either.

Do you UnPossess() your player controllers at the end of the match? APlayerControllers stay around through seamless travel so that RPCs may be called to tell the server that the next level is loaded. A new player controller is created and replicated to the server after this.

Which of the booleans in that code above is keeping it? Is it the Role check only? Or possibly something else?

Hi Josh

Thanks for the reply.
Basically I think the problem is that we need to tidy up our actors on the server when our match ends. At the moment we just assume all the actors will be destroyed when the level ends which is fairly lazy thinking I guess. We also do a fair amount of actor pooling so we will also need to purge our actor pools. Tidying up our actors at the end of the match was already on our roadmap for other reasons but I guess now we have one more reason!

What you’ve said makes a lot of sense to me and I’m pretty confident we can sort this out now.

Thanks for your help,

Mark.