Description

Geometry Collection's Chaos Cache Static Pose Scrubbing broken in 5.6 due to Custom Renderer GeometryCollectionRootProxyRenderer.

The licensee has provided his analysis:
In 5.6, when creating a GeoCollection, it automatically sets a Root Proxy for it. Since GeoCollection uses a custom renderer for Root Proxy, it won't have a SceneProxy created in the editor. Without the SceneProxy, Static Pose scrubbing doesn't work correctly.
This might be a pre-existing bug but exposed by the behavior change in 5.6 that a Root Proxy is now set automatically for newly created GeoCollections.

I've tested in multiple engine versions and noticed the issue is tied to the GeometryCollectionRootProxyRenderer introduced in 5.5 and set as a default in 5.6.
Once we change the CustomRenderer to None, the issue is solved.

This behavior was reproduced in 5.5 (if we manually set the ProxyMesh and CustomRenderer to GeometryCollectionRootProxyRenderer), in 5.6 if we don't disable UseRootProxies during GeometryCollection creation, and in 5.7 (CL44372627).
I've included the Callstack for UGeometryCollectionRootProxyRenderer::UpdateState.

 

Steps to Reproduce

In UE5.6:
In a blank project, create a new scene
Spawn a Cube above ground so it can fall to the floor and break
Select it and go to Fracture Mode (SHIFT+6)
Create New+
Make sure UseRootProxies is enabled (this will setup CustomRenderer as GeometryCollectionRootProxyRenderer)
Fracture the Cube with defaults from Uniform
Back to Selection Mode (SHIFT+1)
Select the GC_Cube and set all DamageThreshold to 1 so it will break once it hit the floor
With GC_Cube selected, go to the menu Actor>Chaos>CreateCacheManager
The ChaosCacheManager (CCM) created comes with CacheMode as RECORD by default
Simulate-In-Editor - this will be recorded by the CCM
Change in the CCM the CacheMode to StaticPose
Select the StartTime and with the mouse scrub to the right, increasing the value
GC_Cube will reproduce the recorded state following the time in StartTime

Expected result: the GC_Cube should fall to the ground and break, matching the timestamp in StartTime
Actual result: once we reach the point where the GC_Cube hits the floor and breaks, GC_Cube resets position

Callstack

> UnrealEditor-GeometryCollectionEngine.dll!UGeometryCollectionRootProxyRenderer::UpdateState(const UGeometryCollection & InGeometryCollection, const UE::Math::TTransform<double> & InComponentTransform, unsigned int InStateFlags) Line 24 C++
UnrealEditor-GeometryCollectionEngine.dll!UGeometryCollectionComponent::RefreshCustomRenderer() Line 6391 C++
UnrealEditor-ChaosCaching.dll!Chaos::FGeometryCollectionCacheAdapter::SetRestState(UPrimitiveComponent * InComponent, UChaosCache * InCache, const UE::Math::TTransform<double> & InRootTransform, double InTime) Line 668 C++
UnrealEditor-ChaosCaching.dll!AChaosCacheManager::OnStartFrameChanged(double InTime) Line 750 C++
UnrealEditor-ChaosCaching.dll!AChaosCacheManager::BeginEvaluate() Line 548 C++
UnrealEditor-Engine.dll!AActor::DispatchBeginPlay(bool bFromLevelStreaming) Line 4713 C++
UnrealEditor-Engine.dll!AWorldSettings::NotifyBeginPlay() Line 362 C++
UnrealEditor-Engine.dll!AGameStateBase::HandleBeginPlay() Line 228 C++
UnrealEditor-Engine.dll!UWorld::BeginPlay() Line 5916 C++
UnrealEditor-Engine.dll!UGameInstance::StartPlayInEditorGameInstance(ULocalPlayer * LocalPlayer, const FGameInstancePIEParameters & Params) Line 567 C++
UnrealEditor-UnrealEd.dll!UEditorEngine::CreateInnerProcessPIEGameInstance(FRequestPlaySessionParams & InParams, const FGameInstancePIEParameters & InPIEParameters, int InPIEInstanceIndex) Line 3182 C++
UnrealEditor-UnrealEd.dll!UEditorEngine::OnLoginPIEComplete_Deferred(int LocalUserNum, bool bWasSuccessful, FString ErrorString, FPieLoginStruct DataStruct) Line 1627 C++
UnrealEditor-UnrealEd.dll!UEditorEngine::CreateNewPlayInEditorInstance(FRequestPlaySessionParams & InRequestParams, const bool bInDedicatedInstance, const EPlayNetMode InNetMode) Line 1890 C++
UnrealEditor-UnrealEd.dll!UEditorEngine::StartPlayInEditorSession(FRequestPlaySessionParams & InRequestParams) Line 2913 C++
UnrealEditor-UnrealEd.dll!UEditorEngine::StartQueuedPlaySessionRequestImpl() Line 1204 C++
UnrealEditor-UnrealEd.dll!UEditorEngine::StartQueuedPlaySessionRequest() Line 1105 C++
UnrealEditor-UnrealEd.dll!UEditorEngine::Tick(float DeltaSeconds, bool bIdleMode) Line 2038 C++
UnrealEditor-UnrealEd.dll!UUnrealEdEngine::Tick(float DeltaSeconds, bool bIdleMode) Line 533 C++
UnrealEditor.exe!FEngineLoop::Tick() Line 5625 C++
[Inline Frame] UnrealEditor.exe!EngineTick() Line 60 C++
UnrealEditor.exe!GuardedMain(const wchar_t * CmdLine) Line 187 C++
UnrealEditor.exe!GuardedMainWrapper(const wchar_t * CmdLine) Line 128 C++
UnrealEditor.exe!LaunchWindowsStartup(HINSTANCE__ * hInInstance, HINSTANCE__ * hPrevInstance, char * __formal, int nCmdShow, const wchar_t * CmdLine) Line 282 C++
UnrealEditor.exe!WinMain(HINSTANCE__ * hInInstance, HINSTANCE__ * hPrevInstance, char * pCmdLine, int nCmdShow) Line 339 C++
[External Code]

Have Comments or More Details?

There's no existing public thread on this issue, so head over to Questions & Answers just mention UE-315559 in the post.

0
Login to Vote

Unresolved
CreatedAug 26, 2025
UpdatedSep 11, 2025
View Jira Issue