FCameraShakePreviewer retains world-outered UCameraShakeBase instances indefinitely, fataling CheckForWorldGCLeaks on editor map change

FCameraShakePreviewer is an FGCObject that strongly references the UCameraShakeBase instances it previews, and creates them outered to the previewed UWorld. Nothing releases them on world teardown, so after a Sequencer camera-shake trigger fires, the next editor map change leaves the outgoing world and its package alive and UEditorEngine::CheckForWorldGCLeaks raises a fatal error.

The only thing that frees the shakes is destruction of FCameraShakePreviewerLinkerExtension, which happens only once both camera-shake systems unlink — but UMovieSceneCameraShakeEvaluatorSystem::IsRelevantImpl reports the system as relevant precisely because the extension still holds a shake. A shake whose pattern never reports IsFinished() therefore pins its own owner permanently.

For now, we made a change to bind FWorldDelegates::OnWorldCleanup in FCameraShakePreviewerLinkerExtension and, on the world being cleaned up, call RemoveAllCameraShakes() on its previewers and drop them from the Previewers map. This releases the GC references before EditorDestroyWorld’s collection and also breaks the relevance cycle, since HasAnyShake() then returns false and the evaluator system can finally unlink.

[Attachment Removed]

Steps to Reproduce

Run unreal at 5.7.4

  1. Open a map in the editor
  2. Open a ULevelSequence containing a camera shake trigger track whose shake class has an infinite / looping pattern (i.e. UCameraShakeBase::IsFinished() never returns true).
  3. Scrub or play the sequence so the trigger fires at least once. TriggerOneShotShakes adds a preview instance via FCameraShakePreviewer::AddCameraShake.
  4. Open a different level (File > Open Level, or any path reaching FEditorFileUtils::LoadMap).
  5. Fatal error as above. Setting gc.historysize 1 first makes the retaining chain visible.
    [Attachment Removed]

Hey there,

Thanks for raising this. I’ve logged an issue that you can follow here: https://issues.unrealengine.com/issue/UE-393044

The change you’ve made seems reasonable, and we don’t have a better answer or workaround.

Dustin

[Attachment Removed]

Hey there, we cannot repro this issue in 5.7. Can you send us a repro of the issue in vanilla unreal?

Dustin

[Attachment Removed]

Attached a very simple project.

  1. Open the project. Ideally with a debugger
  2. Open the level sequence
  3. Move the sequencer time a bit to see camera shake acting
  4. Open the same map (L_TestMap) again without closing the sequence editor
  5. See the crash
    [Attachment Removed]

I got an email saying I should provide additional information, so maybe the last post didn’t register. So I am posting again just in case. Let me know if you need more information

[Attachment Removed]

Hey there, apologies for not responding. We received the repro, and we submitted a fix that follows what you described what you are doing locally.

https://github.com/EpicGames/UnrealEngine/commit/0422764d44e5bb910aec6c91e3cec71620c765c9

Dustin

[Attachment Removed]

Amazing, thank you!

[Attachment Removed]