Description

Under certain conditions, it appears that the function UPoseableMeshComponent::CopyPoseFromSkeletalComponent may crash because the BoneSpaceTransforms obtained from the source component are empty, preventing a successful copy to the destination component. This occurs when an actor's component is being incrementally unregistered during the execution of UWorld::RemoveFromWorld(), and if the unregistering process takes longer than the time limit set by IsTimeLimitExceeded().

TArray<FTransform> LocalTransforms = InComponentToCopy->GetBoneSpaceTransforms(); 

 

Specifically, when the incremental unregistration process is still ongoing and a component belonging to the actor is unregistered, the frame in which BoneSpaceTransforms is cleared in USkinnedMeshComponent::OnUnregister() is different from the frame in which EndPlay is called for the actor. As a result, when CopyPoseFromSkeletalComponent() is called during the actor's Tick function, the BoneSpaceTransforms obtained from GetBoneSpaceTransforms() will be empty.

int32 NumComponentsToUnregister = GLevelStreamingComponentsUnregistrationGranularity;
do
{
   if (Level->IncrementalUnregisterComponents(NumComponentsToUnregister))
   {
      // We're done, so the level can be removed
      CurrentLevelPendingInvisibility = nullptr;
      bFinishRemovingLevel = true;
      break;
   }
} while (!IsTimeLimitExceeded(TEXT("unregistering components"), StartTime, Level, GLevelStreamingUnregisterComponentsTimeLimit)); 

As a temporary workaround, it may be possible to avoid this issue by checking if the component is registered using functions like IsRegistered() in UPoseableMeshComponent::CopyPoseFromSkeletalComponent() and skipping the copy process if it is not.

void UPoseableMeshComponent::CopyPoseFromSkeletalComponent(USkeletalMeshComponent* InComponentToCopy)
{
   // change
   // if(RequiredBones.IsValid())
   if(RequiredBones.IsValid() && IsRegistered()) 

Possibly it may also occur in other feature for animation.

Steps to Reproduce
  1. Open repro project
  2. PIE and use s.UnregisterComponentsTimeLimit 0.016
  3. Press W to advance and load the sublevel.
  4. Press S to take turn and unload the sublevel.
  5. crash occur
Callstack

Assertion failed: (Index >= 0) & (Index < ArrayNum) [Link Removed] [Line: 763] Array index out of bounds: 0 from an array of size 0

UnrealEditor_Engine!UPoseableMeshComponent::CopyPoseFromSkeletalComponent() [D:\build\++UE5\Sync\Engine\Source\Runtime\Engine\Private\Components\PoseableMeshComponent.cpp:311]
UnrealEditor_Engine!UPoseableMeshComponent::execCopyPoseFromSkeletalComponent() [D:\build\++UE5\Sync\Engine\Intermediate\Build\Win64\UnrealEditor\Inc\Engine\UHT\PoseableMeshComponent.gen.cpp:29]
UnrealEditor_CoreUObject!UFunction::Invoke() [D:\build\++UE5\Sync\Engine\Source\Runtime\CoreUObject\Private\UObject\Class.cpp:6455]
UnrealEditor_CoreUObject!UObject::CallFunction() [D:\build\++UE5\Sync\Engine\Source\Runtime\CoreUObject\Private\UObject\ScriptCore.cpp:1129]
UnrealEditor_CoreUObject!UObject::ProcessContextOpcode() [D:\build\++UE5\Sync\Engine\Source\Runtime\CoreUObject\Private\UObject\ScriptCore.cpp:3139]
UnrealEditor_CoreUObject!ProcessLocalScriptFunction() [D:\build\++UE5\Sync\Engine\Source\Runtime\CoreUObject\Private\UObject\ScriptCore.cpp:1199]
UnrealEditor_CoreUObject!ProcessScriptFunction<void (__cdecl*)(UObject *,FFrame &,void *)>() [D:\build\++UE5\Sync\Engine\Source\Runtime\CoreUObject\Private\UObject\ScriptCore.cpp:1029]
UnrealEditor_CoreUObject!ProcessLocalFunction() [D:\build\++UE5\Sync\Engine\Source\Runtime\CoreUObject\Private\UObject\ScriptCore.cpp:1269]
UnrealEditor_CoreUObject!ProcessLocalScriptFunction() [D:\build\++UE5\Sync\Engine\Source\Runtime\CoreUObject\Private\UObject\ScriptCore.cpp:1199]
UnrealEditor_CoreUObject!UObject::ProcessInternal() [D:\build\++UE5\Sync\Engine\Source\Runtime\CoreUObject\Private\UObject\ScriptCore.cpp:1296]
UnrealEditor_CoreUObject!UFunction::Invoke() [D:\build\++UE5\Sync\Engine\Source\Runtime\CoreUObject\Private\UObject\Class.cpp:6455]
UnrealEditor_CoreUObject!UObject::ProcessEvent() [D:\build\++UE5\Sync\Engine\Source\Runtime\CoreUObject\Private\UObject\ScriptCore.cpp:2127]
UnrealEditor_Engine!AActor::ProcessEvent() [D:\build\++UE5\Sync\Engine\Source\Runtime\Engine\Private\Actor.cpp:1055]
UnrealEditor_Engine!AActor::ReceiveTick() [D:\build\++UE5\Sync\Engine\Intermediate\Build\Win64\UnrealEditor\Inc\Engine\UHT\Actor.gen.cpp:2161]
UnrealEditor_Engine!AActor::Tick() [D:\build\++UE5\Sync\Engine\Source\Runtime\Engine\Private\Actor.cpp:1430]
UnrealEditor_Engine!AActor::TickActor() [D:\build\++UE5\Sync\Engine\Source\Runtime\Engine\Private\Actor.cpp:1410]
UnrealEditor_Engine!FActorTickFunction::ExecuteTick() [D:\build\++UE5\Sync\Engine\Source\Runtime\Engine\Private\Actor.cpp:222]
UnrealEditor_Engine!FTickFunctionTask::DoTask() [D:\build\++UE5\Sync\Engine\Source\Runtime\Engine\Private\TickTaskManager.cpp:284]
UnrealEditor_Engine!TGraphTask<FTickFunctionTask>::ExecuteTask() [D:\build\++UE5\Sync\Engine\Source\Runtime\Core\Public\Async\TaskGraphInterfaces.h:1348]
UnrealEditor_Core!FNamedTaskThread::ProcessTasksNamedThread() [D:\build\++UE5\Sync\Engine\Source\Runtime\Core\Private\Async\TaskGraph.cpp:760]
UnrealEditor_Core!FNamedTaskThread::ProcessTasksUntilQuit() [D:\build\++UE5\Sync\Engine\Source\Runtime\Core\Private\Async\TaskGraph.cpp:649]
UnrealEditor_Core!FTaskGraphCompatibilityImplementation::WaitUntilTasksComplete() [D:\build\++UE5\Sync\Engine\Source\Runtime\Core\Private\Async\TaskGraph.cpp:2203]
UnrealEditor_Engine!FTickTaskSequencer::ReleaseTickGroup() [D:\build\++UE5\Sync\Engine\Source\Runtime\Engine\Private\TickTaskManager.cpp:565]
UnrealEditor_Engine!FTickTaskManager::RunTickGroup() [D:\build\++UE5\Sync\Engine\Source\Runtime\Engine\Private\TickTaskManager.cpp:1592]
UnrealEditor_Engine!UWorld::RunTickGroup() [D:\build\++UE5\Sync\Engine\Source\Runtime\Engine\Private\LevelTick.cpp:794]
UnrealEditor_Engine!UWorld::Tick() [D:\build\++UE5\Sync\Engine\Source\Runtime\Engine\Private\LevelTick.cpp:1537]
UnrealEditor_UnrealEd!UEditorEngine::Tick() [D:\build\++UE5\Sync\Engine\Source\Editor\UnrealEd\Private\EditorEngine.cpp:1890]
UnrealEditor_UnrealEd!UUnrealEdEngine::Tick() [D:\build\++UE5\Sync\Engine\Source\Editor\UnrealEd\Private\UnrealEdEngine.cpp:517]
UnrealEditor!FEngineLoop::Tick() [D:\build\++UE5\Sync\Engine\Source\Runtime\Launch\Private\LaunchEngineLoop.cpp:5369]
UnrealEditor!GuardedMain() [D:\build\++UE5\Sync\Engine\Source\Runtime\Launch\Private\Launch.cpp:202]
UnrealEditor!GuardedMainWrapper() [D:\build\++UE5\Sync\Engine\Source\Runtime\Launch\Private\Windows\LaunchWindows.cpp:107]
UnrealEditor!LaunchWindowsStartup() [D:\build\++UE5\Sync\Engine\Source\Runtime\Launch\Private\Windows\LaunchWindows.cpp:244]
UnrealEditor!WinMain() [D:\build\++UE5\Sync\Engine\Source\Runtime\Launch\Private\Windows\LaunchWindows.cpp:282]
UnrealEditor!__scrt_common_main_seh() [D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:288]
kernel32
ntdl

Have Comments or More Details?

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

1
Login to Vote

Fixed
ComponentUE - Anim - Runtime
Affects Versions4.27.25.05.15.2
Target Fix5.3
Fix Commit26568345
Main Commit26570104
CreatedApr 26, 2023
ResolvedJul 28, 2023
UpdatedJul 28, 2023