Description

Enabling bUpdateComponentTransformToRootBone in a GeometryCollectionComponent causes broken particles to appear in the wrong location. When that flag is true, the moment the GeometryCollection (GC) breaks, the component is teleported, and the new position looks proportional to the distance traveled before hitting the surface.
Verification on ChaosVisualDebugger indicates the GC is behaving as expected on the physics side. It looks like only the rendering is transported to the wrong place.
I've confirmed this issue reproduces on UE5.4, 5.5, 5.6, and 5.7 (CL43620315).
I was not able to pinpoint the cause, but I've included the callstack for USceneComponent::SetRelativeTransform, as I suspect the issue might be on that path.

 

Steps to Reproduce

The licensee has provided a repro project. To use it just simulate the scene.

From scratch:
In a blank project, create a basic scene
Add a Cube and scale and rotate it so it forms a tilted surface for the GeometryCollection (GC) to collide against once it falls over it
Add another cube immediately above and make it a GC by fracturing and setting the damage threshold to a low value (1.0) so it always breaks upon impact
Set bUpdateComponentTransformToRootBone to true in the GC
The result depends on the distance between the tilted surface and the GC, so make sure the distance between them is around 500 units
With the GC selected (for easier visualization), simulate the scene
Check as the GC hits the tilted surface and breaks

Expected result: the GC fragments should scatter as if they broke on impact with the hard surface and slide over it
Actual result: the GC fragments are teleported below the hard surface, and the distance is proportional to how much it travelled before hitting the surface.

Callstack

> UnrealEditor-Engine.dll!USceneComponent::SetRelativeTransform(const UE::Math::TTransform<double> & NewTransform, bool bSweep, FHitResult * OutSweepHitResult, ETeleportType Teleport) Line 1874 C++
UnrealEditor-GeometryCollectionEngine.dll!UGeometryCollectionRootProxyRenderer::UpdateRootProxyTransforms(const UGeometryCollection & InGeometryCollection, const UE::Math::TTransform<double> & InRootTransform, TArrayView<UE::Math::TTransform<float> const ,int> InLocalRootTransforms) Line 90 C++
UnrealEditor-GeometryCollectionEngine.dll!UGeometryCollectionRootProxyRenderer::UpdateRootTransforms(const UGeometryCollection & InGeometryCollection, const UE::Math::TTransform<double> & InRootTransform, TArrayView<UE::Math::TTransform<float> const ,int> InRootTransforms) Line 51 C++
UnrealEditor-GeometryCollectionEngine.dll!UGeometryCollectionComponent::RefreshCustomRenderer() Line 6403 C++
UnrealEditor-GeometryCollectionEngine.dll!UGeometryCollectionComponent::UpdateRenderSystemsIfNeeded(bool bDynamicCollectionDirty) Line 4426 C++
UnrealEditor-GeometryCollectionEngine.dll!UGeometryCollectionComponent::OnPostPhysicsSync() Line 4340 C++
[Inline Frame] UnrealEditor-Chaos.dll!UE::Core::Private::Function::TFunctionRefBase<UE::Core::Private::Function::TFunctionStorage<0>,void __cdecl(void)>::operator()() Line 471 C++
UnrealEditor-Chaos.dll!FGeometryCollectionPhysicsProxy::PullFromPhysicsState(const Chaos::FDirtyGeometryCollectionData & PullData, const int SolverSyncTimestamp, const Chaos::FDirtyGeometryCollectionData * NextPullData, const float * Alpha, const Chaos::FDirtyRigidParticleReplicationErrorData * Error, const double AsyncFixedTimeStep) Line 4636 C++
UnrealEditor-Engine.dll!Chaos::FPhysicsSolverBase::PullPhysicsStateForEachDirtyProxy_External<`FPhysScene_Chaos::OnSyncBodies'::`2'::FDispatcher>(FPhysScene_Chaos::OnSyncBodies::__l2::FDispatcher & Dispatcher) Line 164 C++
[Inline Frame] UnrealEditor-Engine.dll!UE::Core::Private::Function::TFunctionRefBase<UE::Core::Private::Function::FFunctionRefStoragePolicy,void __cdecl(FPhysScene_Chaos *)>::operator()(FPhysScene_Chaos * <Params_0>) Line 471 C++
UnrealEditor-Engine.dll!FPhysInterface_Chaos::ExecuteWrite(FPhysScene_Chaos * InScene, TFunctionRef<void __cdecl(FPhysScene_Chaos *)> InCallable) Line 652 C++
UnrealEditor-Engine.dll!FPhysScene_Chaos::OnSyncBodies(Chaos::FPhysicsSolverBase * Solver) Line 2526 C++
UnrealEditor-PhysicsCore.dll!FChaosScene::SyncBodies<Chaos::FPBDRigidsSolver>(Chaos::FPBDRigidsSolver * Solver) Line 451 C++
UnrealEditor-PhysicsCore.dll!??$?RVFPBDRigidsSolver@Chaos@@@<lambda_1>@?EK@??EndFrame@FChaosScene@@QEAAXXZ@QEBA?A_PAEAVFPBDRigidsSolver@Chaos@@@Z(Chaos::FPBDRigidsSolver & Concrete) Line 566 C++
[Inline Frame] UnrealEditor-PhysicsCore.dll!Chaos::FPhysicsSolverBase::CastHelper(const FChaosScene::EndFrame::__l74::<lambda_1> &) Line 318 C++
UnrealEditor-PhysicsCore.dll!FChaosScene::EndFrame() Line 561 C++
[Inline Frame] UnrealEditor-Engine.dll!Invoke(void(UWorld::*)()) Line 66 C++
[Inline Frame] UnrealEditor-Engine.dll!UE::Core::Private::Tuple::TTupleBase<TIntegerSequence<unsigned int>>::ApplyAfter(void(UWorld::*)() &) Line 320 C++
UnrealEditor-Engine.dll!V::TBaseUObjectMethodDelegateInstance::ExecuteIfSafe() Line 689 C++
[Inline Frame] UnrealEditor-Engine.dll!TDelegate<void __cdecl(void),FDefaultDelegateUserPolicy>::ExecuteIfBound() Line 635 C++
[Inline Frame] UnrealEditor-Engine.dll!FSimpleDelegateGraphTask::DoTask(ENamedThreads::Type) Line 958 C++
UnrealEditor-Engine.dll!TGraphTask<FSimpleDelegateGraphTask>::ExecuteTask() Line 706 C++
UnrealEditor-Core.dll!UE::Tasks::Private::FTaskBase::TryExecuteTask() Line 527 C++
[Inline Frame] UnrealEditor-Core.dll!FBaseGraphTask::Execute(TArray<FBaseGraphTask *,TSizedDefaultAllocator<32>> &) Line 505 C++
UnrealEditor-Core.dll!FNamedTaskThread::ProcessTasksNamedThread(int QueueIndex, bool bAllowStall) Line 779 C++
UnrealEditor-Core.dll!FNamedTaskThread::ProcessTasksUntilQuit(int QueueIndex) Line 668 C++
[Inline Frame] UnrealEditor-Core.dll!FTaskGraphCompatibilityImplementation::ProcessThreadUntilRequestReturn(ENamedThreads::Type) Line 1428 C++
UnrealEditor-Core.dll!FTaskGraphCompatibilityImplementation::WaitOnNamedThreadForTasks(const TArray<TRefCountPtr<FBaseGraphTask>,TSizedInlineAllocator<4,32,TSizedDefaultAllocator<32>>> & Tasks, ENamedThreads::Type BaseNamedThread, ENamedThreads::Type NamedThreadWithFlags) Line 1486 C++
UnrealEditor-Core.dll!FTaskGraphCompatibilityImplementation::ProcessUntilTasksComplete(const TArray<TRefCountPtr<FBaseGraphTask>,TSizedInlineAllocator<4,32,TSizedDefaultAllocator<32>>> & Tasks, ENamedThreads::Type CurrentThreadIfKnown, const TFunction<enum FTaskGraphInterface::EProcessTasksOperation __cdecl(int)> & IdleWorkUpdate) Line 1585 C++
UnrealEditor-Engine.dll!FTickTaskSequencer::ReleaseTickGroup(ETickingGroup WorldTickGroup, bool bBlockTillComplete, TArray<FTickFunction *,TSizedDefaultAllocator<32>> & TicksToManualDispatch) Line 986 C++
UnrealEditor-Engine.dll!FTickTaskManager::RunTickGroup(ETickingGroup Group, bool bBlockTillComplete) Line 2079 C++
UnrealEditor-Engine.dll!UWorld::RunTickGroup(ETickingGroup Group, bool bBlockTillComplete) Line 786 C++
UnrealEditor-Engine.dll!UWorld::Tick(ELevelTick TickType, float DeltaSeconds) Line 1533 C++
UnrealEditor-UnrealEd.dll!UEditorEngine::Tick(float DeltaSeconds, bool bIdleMode) Line 2151 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!LaunchWindowsStartup(HINSTANCE__ * hInInstance, HINSTANCE__ * hPrevInstance, char * __formal, int nCmdShow, const wchar_t * CmdLine) Line 271 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-297788 in the post.

0
Login to Vote

Unresolved
ComponentUE - Simulation - Physics - Destruction
Affects Versions5.45.55.65.7
CreatedJun 22, 2025
UpdatedJul 17, 2025
View Jira Issue