Crash with Cesium3DTileset when Changing Levels While Still Loading

Hello everyone,

We’re encountering a crash in Cesium for Unreal related to a Cesium3DTileset actor being destroyed while it’s still loading. Specifically, when the Cesium3DTileset is actively generating a GLTF component and we change to a different level, the actor is destroyed—leading to a crash.

Currently, we call suspendUpdate = true before changing levels, but in certain cases Cesium still tries to generate a GLTF component afterward. The full stack trace (below) shows the crash occurring during the finalization of the GLTF creation.

Additionally, we spawn our AActor dynamically in the Persistent Level. It used to remain alive until we manually destroyed it, but now it appears to be garbage-collected automatically when levels change—even though it’s still on the Persistent Level.

Our questions:

  1. Is there a way to reliably detect if the Cesium3DTileset is still processing or loading? We’d like to ensure that all pending requests finish before changing levels.
  2. Have there been any recent changes to actor lifecycle behavior on level transitions that might affect a dynamically spawned actor in the Persistent Level?

Attached is the relevant log information, including a disk I/O error from the SqliteCache and a subsequent critical error referencing an invalid TArray size:

message (28).txt.zip (2.2 KB)

We suspect we need to either:

  • Wait until the final GLTF component generation finishes, or
  • Prevent the AActor from being destroyed until all pending loads have completed.

If anyone has insights or solutions for handling these scenarios—particularly regarding actor lifecycle changes when switching levels—please let us know. Thank you for taking a look @Kevin_Ring

Hi @carlrealvr,

Cesium3DTileset has logic to prevent it from being fully destroyed until all async requests complete. The way it works is that DestroyTileset increments _tilesetsBeingDestroyed, and decrements it in a subscription to the cesium-native Tileset’s getAsyncDestructionCompleteEvent. Then, IsReadyForFinishDestroy returns false until that counter goes to zero. IsReadyForFinishDestroy is part of Unreal’s garbage collector, and prevents the object’s memory from being freed - and the level unload from completing - until it returns true.

It sounds like this isn’t working for you, but I don’t know why that might be. Can you help us reproduce the problem ourselves so that we can take a look?

We managed to resolve the issue! The problem was related to how we were spawning the 3D tileset actors (CityActors) dynamically.

Initially, we were assigning ownership of the CityActors to a ManagerActor that only existed in the sub-level. When switching levels, the ManagerActor in the sub-level was destroyed, which in turn forced the destruction of all CityActors due to their ownership relationship.

The solution was to ensure that the CityActors are owned by an actor that resides in the Persistent Level. By doing this, the CityActors are no longer tied to the lifecycle of the sub-level, preventing them from being unintentionally destroyed during level transitions.

Hopefully, this helps anyone encountering a similar issue. Thanks @Kevin_Ring and I’ll mark this as resolved

Good to hear you figured it out @carlrealvr, and thanks for sharing your solution!

1 Like