Description

When a SkeletalMeshComponent is restarted by calling in order of 
 SetSimulatePhysics and SetComponentTickEnabled, the TickComponent and EndPhysicsTick are executed simultaneously. As a result, the RequiredBones array is written and read at the same time.

See callstack for datail.

The cause is that the HighPriority flag of the PrimaryComponentTick is set at the TickComponent. The workaround is to pre-set this flag in RegisterComponentTickFunctions or similar.

void USkeletalMeshComponent::RegisterComponentTickFunctions(bool bRegister)
{
	Super::RegisterComponentTickFunctions(bRegister);

//workaround
	bool bDoHiPri = CVarHiPriSkinnedMeshesTicks.GetValueOnGameThread() > 0;
	if (PrimaryComponentTick.bHighPriority != bDoHiPri)
	{
		PrimaryComponentTick.SetPriorityIncludingPrerequisites(bDoHiPri);
	}
//workaround ends
	UpdateEndPhysicsTickRegisteredState();
	UpdateClothTickRegisteredState();
}

 

Steps to Reproduce
  1. Compile and launch attached project on 4.27 engine. [Link Removed]
  2. Start PIE and wait a while

Result:

Assertion failed occurs with log:

Assertion failed: (Index >= 0) & (Index < ArrayNum) [File:D:\dev\UnrealEngine-4.27.2\Engine\Source\Runtime\Core\Public\Containers/Array.h] [Line: 703] 
Array index out of bounds: 11 from an array of size 68

 

Callstack

callstack for assertion

>	[Inline Frame] UE4Editor-Engine.dll!TArray<unsigned short,TSizedDefaultAllocator<32>>::RangeCheck(int Index) Line 703	C++
 	[Inline Frame] UE4Editor-Engine.dll!TArray<unsigned short,TSizedDefaultAllocator<32>>::operator[](int) Line 760	C++
 	UE4Editor-Engine.dll!USkeletalMeshComponent::PerformBlendPhysicsBones::__l2::<lambda>() Line 204	C++
 	[Inline Frame] UE4Editor-Engine.dll!UE4Function_Private::TFunctionRefBase<UE4Function_Private::FFunctionRefStoragePolicy,void __cdecl(void)>::operator()() Line 676	C++
 	UE4Editor-Engine.dll!FPhysicsCommand_PhysX::ExecuteRead(USkeletalMeshComponent * InMeshComponent, TFunctionRef<void __cdecl(void)> InCallable) Line 570	C++
 	UE4Editor-Engine.dll!USkeletalMeshComponent::PerformBlendPhysicsBones(const TArray<unsigned short,TSizedDefaultAllocator<32>> & InRequiredBones, TArray<FTransform,TSizedDefaultAllocator<32>> & InOutComponentSpaceTransforms, TArray<FTransform,TSizedDefaultAllocator<32>> & InOutBoneSpaceTransforms) Line 195	C++
 	[Inline Frame] UE4Editor-Engine.dll!USkeletalMeshComponent::ParallelBlendPhysics() Line 2276	C++
 	[Inline Frame] UE4Editor-Engine.dll!FParallelBlendPhysicsTask::DoTask(ENamedThreads::Type) Line 78	C++
 	UE4Editor-Engine.dll!TGraphTask<FParallelBlendPhysicsTask>::ExecuteTask(TArray<FBaseGraphTask *,TSizedDefaultAllocator<32>> & NewTasks, ENamedThreads::Type CurrentThread) Line 886	C++
 	[Inline Frame] UE4Editor-Core.dll!FBaseGraphTask::Execute(TArray<FBaseGraphTask *,TSizedDefaultAllocator<32>> & CurrentThread, ENamedThreads::Type) Line 524	C++
 	UE4Editor-Core.dll!FTaskThreadAnyThread::ProcessTasks() Line 1066	C++
 	UE4Editor-Core.dll!FTaskThreadAnyThread::ProcessTasksUntilQuit(int QueueIndex) Line 889	C++
 	[Inline Frame] UE4Editor-Core.dll!FTaskThreadBase::Run() Line 541	C++
 	UE4Editor-Core.dll!FTaskThreadAnyThread::Run() Line 966	C++
 	UE4Editor-Core.dll!FRunnableThreadWin::Run() Line 86	C++
 	UE4Editor-Core.dll!FRunnableThreadWin::GuardedRun() Line 27	C++
 	[External Code]	

Write access

USkeletalMeshComponent::ComputeRequiredBones(TArray<unsigned short,TSizedDefaultAllocator<32>> & OutRequiredBones, TArray<unsigned short,TSizedDefaultAllocator<32>> & OutFillComponentSpaceTransformsRequiredBones, int LODIndex, bool bIgnorePhysicsAsset) 行 1676	C++
USkeletalMeshComponent::RecalcRequiredBones(int LODIndex) 行 1829	C++
USkeletalMeshComponent::RefreshBoneTransforms(FActorComponentTickFunction * TickFunction) 行 2194	C++
USkinnedMeshComponent::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction * ThisTickFunction) 行 875	C++
USkeletalMeshComponent::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction * ThisTickFunction) 行 1376	C++
FActorComponentTickFunction::ExecuteTick(float DeltaTime, ELevelTick TickType, ENamedThreads::Type CurrentThread, const TRefCountPtr<FGraphEvent> & MyCompletionGraphEvent) 行 1088	C++
FTickFunctionTask::DoTask(ENamedThreads::Type CurrentThread, const TRefCountPtr<FGraphEvent> & MyCompletionGraphEvent) 行 290	C++
TGraphTask<FTickFunctionTask>::ExecuteTask(TArray<FBaseGraphTask *,TSizedDefaultAllocator<32>> & NewTasks, ENamedThreads::Type CurrentThread) 行 889	C++
FBaseGraphTask::Execute(TArray<FBaseGraphTask *,TSizedDefaultAllocator<32>> & CurrentThread, ENamedThreads::Type) 行 524	C++
FNamedTaskThread::ProcessTasksNamedThread(int QueueIndex, bool bAllowStall) 行 710	C++
FNamedTaskThread::ProcessTasksUntilQuit(int QueueIndex) 行 602	C++
FTaskGraphImplementation::ProcessThreadUntilRequestReturn(ENamedThreads::Type CurrentThread) 行 1480	C++
FTaskGraphImplementation::WaitUntilTasksComplete() 行 1532	C++
FTickTaskSequencer::ReleaseTickGroup(ETickingGroup WorldTickGroup, bool bBlockTillComplete) 行 569	C++
FTickTaskManager::RunTickGroup(ETickingGroup Group, bool bBlockTillComplete) 行 1611	C++
UWorld::RunTickGroup(ETickingGroup Group, bool bBlockTillComplete) 行 792	C++
UWorld::Tick(ELevelTick TickType, float DeltaSeconds) 行 1637	C++
UGameEngine::Tick(float DeltaSeconds, bool bIdleMode) 行 1827	C++
FEngineLoop::Tick() 行 4921	C++
EngineTick() 行 62	C++
GuardedMain(const wchar_t * CmdLine) 行 178	C++

Read access

USkeletalMeshComponent::PerformBlendPhysicsBones::__l2::<ラムダ>() 行 203	C++
UE4Function_Private::TFunctionRefBase<UE4Function_Private::FFunctionRefStoragePolicy,void __cdecl(void)>::operator()() 行 676	C++
FPhysicsCommand_PhysX::ExecuteRead(USkeletalMeshComponent * InMeshComponent, TFunctionRef<void __cdecl(void)> InCallable) 行 570	C++
USkeletalMeshComponent::PerformBlendPhysicsBones(const TArray<unsigned short,TSizedDefaultAllocator<32>> & InRequiredBones, TArray<FTransform,TSizedDefaultAllocator<32>> & InOutComponentSpaceTransforms, TArray<FTransform,TSizedDefaultAllocator<32>> & InOutBoneSpaceTransforms) 行 325	C++
FCpuProfilerTrace::FEventScope::{ctor}(unsigned int InSpecId, const Trace::FChannel & Channel) 行 76	C++
FParallelBlendPhysicsTask::DoTask(ENamedThreads::Type) 行 77	C++
TGraphTask<FParallelBlendPhysicsTask>::ExecuteTask() 行 886	C++
FBaseGraphTask::Execute() 行 524	C++
FTaskThreadAnyThread::ProcessTasks() 行 1066	C++
FTaskThreadAnyThread::ProcessTasksUntilQuit() 行 889	C++
FTaskThreadBase::Run() 行 541	C++
FTaskThreadAnyThread::Run() 行 966	C++
FRunnableThreadWin::Run() 行 86	C++
FRunnableThreadWin::GuardedRun() 行 27	C++

Have Comments or More Details?

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

3
Login to Vote

Fixed
ComponentUE - Anim - Runtime
Affects Versions4.275.2
Target Fix5.2
Fix Commit24634744
Main Commit24636308
Release Commit24634744
CreatedJan 18, 2023
ResolvedMar 14, 2023
UpdatedApr 29, 2023