Keeping Actors Between Levels

Is there a way through either C++ or Blueprint for me to keep an Actor between levels, much like Unity’s DoNotDelete?

Particular use case I’m thinking of is an Actor that is handling communication with a server (not UE4 server). Obviously if I’m switching between levels I don’t want to lose my connection, and I also don’t want to have to reconnect.

Streaming may work, but I’d like to cover all my bases here.

3 Likes

At the moment there are few ways to keep actors alive between levels, and we are discussing a new idea to help this going forward.

For now you’ll want to use “seamless travel”, which keeps network connections alive between server/clients while loading the next map/level. On the AGameMode there is a boolean “bUseSeamlessTravel”, that will make sure calls to ServerTravel will go a different path when loading maps. Seamless travel basically loads a small map as a transition so that it can garbage collect the previous map. It then continues to load the destination map afterward. This way, we can prevent a memory high watermark and possible out of memory conditions on limited memory platforms (ie console). You’ll need to specify a small transition map in DefaultEngine.ini

[/Script/EngineSettings.GameMapsSettings]
TransitionMap=/Game/Maps/SmallTransitionMap

With seamless travel, there is a call GetSeamlessTravelActorList which will allow you to add actors to an array of AActors to preserve between levels. It guarantees they won’t garbage collected and will be “renamed” into the next level. I don’t know why it’s called Rename, but basically it moves the AActor into the next UWorld and in fact the name does change (the FName gets its _ number incremented).

Now, not many things get preserved across travel, the point being that whatever object had a pointer to the object you’re preserving is probably getting garbage collected, so the direct reference to your AActor is going to be lost. APlayerController typically survives longer than other AActors (unless the class of controller is changing). You can always do a TActorIterator<ClassToSave> to find the object(s) again and reestablish the linkage. There are a couple of places at this transition where you still have the old AGameMode and AGameState and could theoretically hand off a pointer, but I just looked and it isn’t well exposed in an overload fashion (ie you’d have to modify the engine code a little).

The GetSeamlessTravelActorList function will be called twice, once when the transition map is reached, and again when the destination map is reached.

Hope this helps, let me know any addition questions you have as you work through this.

1 Like

This sounds like it will do the trick. I’ll try it out and reply in this thread if it doesn’t.

Thanks!

Please do followup with any minutiae that I might have missed so others may follow your lead.

As a last resort, you can always manage object lifetime yourself with AddToRoot() and RemoveFromRoot(), which will prevent object garbage collection. Be aware, that you cannot do this with an AActor. I’ve worked around this though in the past by preserving the “guts” of an AActor in a UObject and restoring it on a newly spawned actor on the other side.

Happy to help.

does it work?

can u explain this method?
a little code snippet could have save pain of testing out seemless travel part.
i only need to protect one actor from garbage collection.
thanks

Look at the relationship between UPartyBeaconState and APartyBeaconHost to see how one contains the other and allows the actor class to be reinitialized from the UObject class.

1 Like

The GetSeamlessTravelActorList function will be called twice, once when the transition map is reached, and again when the destination map is reached.

Has there been an update to this? I know this is very old, but I need something similar to this.

The thing is, i want to load a new map without destroying the old one, so I can use it for some advanced ingame HUD stuff (like having an inventory with your character moving around.)
Now, I could save the whole world, open a new level, display the inventory and when done, save everything again, load the previous map alogn with the state i had saved, so i can apply all the changes.
This seems like a real round-about way though.

I dont understand why it’s not possible to open a new map, while detaching the old map (keeping it alive, but inactive, as if it was paused), so all the actors and objects would still remain in memory. When going back to the original map, nothing would have to be loaded. The old world just would have to be reattached and reinstantiated as the real world again.

I know this is very late but I think I have an answer to this.
By streaming a Level, you can have multiple maps at the same time and can set some Maps to inactive.
This might help: Level Streaming Overview in Unreal Engine | Unreal Engine 5.3 Documentation

Thanks for the answer :slight_smile: I knew about this but it does have it’s own downsides. For example, the levels streamed in still exist in the same world. They share the same lighting etc. So if I wanted to have a map for my inventory, which has his own lighting etc., I would somehow have to find a way to isolate it from the game world/maps. I dont see level streaming fixing this. Do you?

A way to fix this would be to put the inventory area lets say below the normal ground, and then you could just teleport the player back and forth and keep a kind of separate lighting.

how do I GetSeamlessTravelActorList in blueprints?