Hello,
We recently had a few occurrences of crashes caused by a “Fatal world leaks detected” error when unloading a level (in a packaged game and in editor).
I tracked down what was keeping a references to a uobject preventing the world to be GCed and it led me to the sequencer, a TStrongObjectPtr was still holding a reference to an animation blueprint. The pointer was assigned by OutCachedValue.CachedAnimInstance.Reset(Component->AnimScriptInstance); in FPreAnimatedSkeletalAnimationTraits::CachePreAnimatedValue() but FPreAnimatedSkeletalAnimationTraits::RestorePreAnimatedValue was never called even though the sequence had stopped playing.
It turns out that this issue happen in some very specific conditions. I’ve put some details in the repro steps and project, but the main factors are the following:
- a level sequence plays an animation on a skeletal mesh’s animation blueprint
- it also spawns an actor that plays a second sequence (through an actor sequence component in our case)
What happens is that when the main sequence stops:
- FMovieSceneEntitySystemRunner::QueueFinalUpdate() and then FMovieSceneEntitySystemRunner::FlushOutstanding() is called
- During the ERunnerFlushState::Import phase, in FSequenceInstance::Finish(), a call to Ledger.UnlinkEverything(Linker) adds a NeedsUnlink component to the sequence’s entities.
- Further in the same Finish() function, a call to SpawnRegister->CleanUp() does a DestroyObjectsByPredicate() and destroys spawned actors
- When the spawned actors gets destroyed, in our case UActorSequenceComponent::EndPlay is called and the playing sequence is stopped
- In SequencePlayer->TearDown(), UMovieSceneEntitySystemLinker::CleanGarbage() endup being called
- In UMovieSceneEntitySystemLinker::CleanGarbage(), a EntityManager.FreeEntities() is done on all entities with a NeedsUnlink component, thus wiping the work that was done in the Import phase
- Later in the Instantiation phase, UMovieSceneRestorePreAnimatedStateSystem::OnRun() won’t find any entities with the NeedsUnlink component to cleanup so RestorePreAnimatedValue() won’t be called
In order to fix this issue, in UMovieSceneEntitySystemLinker::CleanGarbage() I added a check to see if an evaluation phase was already in progress before doing a FreeEntities:
[Image Removed]
In this case the ResetRunner() and the subsequence evaluation restart should take care of the cleanup if I’m not mistaken.
Let me know if it’s a know issue on your side, and if this fix seems valid to you or if there is a better way to handle this situation.