248 if (WorldBoneTMs[BoneIndex].bUpToDate)
253 FTransform ParentTM, RelTM;
257 ParentTM = LocalToWorldTM;
262 int32 ParentIndex = SkelComp->SkeletalMesh->GetRefSkeleton().GetParentIndex(BoneIndex);
263 UpdateWorldBoneTMVR(WorldBoneTMs, InBoneSpaceTransforms, ParentIndex, SkelComp, LocalToWorldTM, Scale3D);
264 ParentTM = WorldBoneTMs[ParentIndex].TM;
267 if (InBoneSpaceTransforms.IsValidIndex(BoneIndex))
269 RelTM = InBoneSpaceTransforms[BoneIndex];
270 RelTM.ScaleTranslation(Scale3D);
272 WorldBoneTMs[BoneIndex].TM = RelTM * ParentTM;
273 WorldBoneTMs[BoneIndex].bUpToDate =
true;
281 FVector TotalScale3D = GetComponentTransform().GetScale3D();
282 FVector RecipScale3D = TotalScale3D.Reciprocal();
284 UPhysicsAsset*
const PhysicsAsset = GetPhysicsAsset();
287 if (GetNumComponentSpaceTransforms() == 0)
293 FPhysScene* PhysScene =
nullptr;
294 if (GetWorld() !=
nullptr)
296 PhysScene = GetWorld()->GetPhysicsScene();
299 if (PhysScene ==
nullptr)
304 FMemMark Mark(FMemStack::Get());
307 WorldBoneTMs.AddZeroed(GetNumComponentSpaceTransforms());
309 FTransform LocalToWorldTM = GetComponentTransform();
312 LocalToWorldTM.SetScale3D(LocalToWorldTM.GetScale3D().GetSignVector());
313 LocalToWorldTM.NormalizeRotation();
316 TArray<FTransform>& EditableComponentSpaceTransforms = GetEditableComponentSpaceTransforms();
324 FPhysicsCommand::ExecuteRead(
this, [&]()
326 bool bSetParentScale =
false;
327 const bool bSimulatedRootBody = Bodies.IsValidIndex(RootBodyData.BodyIndex) && Bodies[RootBodyData.BodyIndex]->IsInstanceSimulatingPhysics();
328 const FTransform NewComponentToWorld = bSimulatedRootBody ? GetComponentTransformFromBodyInstance(Bodies[RootBodyData.BodyIndex]) : FTransform::Identity;
331 for (int32 i = 0; i < InRequiredBones.Num(); i++)
333 int32 BoneIndex = InRequiredBones[i];
336 int32 BodyIndex = PhysicsAsset->FindBodyIndex(SkeletalMesh->GetRefSkeleton().GetBoneName(BoneIndex));
338 FBodyInstance* PhysicsAssetBodyInstance =
nullptr;
341 if (BodyIndex != INDEX_NONE)
343 PhysicsAssetBodyInstance = Bodies[BodyIndex];
346 if (PhysicsAssetBodyInstance->IsInstanceSimulatingPhysics())
348 FTransform PhysTM = PhysicsAssetBodyInstance->GetUnrealWorldTransform_AssumesLocked();
351 WorldBoneTMs[BoneIndex].TM = PhysTM;
352 WorldBoneTMs[BoneIndex].bUpToDate =
true;
354 float UsePhysWeight = (bBlendPhysics) ? 1.f : PhysicsAssetBodyInstance->PhysicsBlendWeight;
357 FTransform ParentWorldTM;
360 if (UsePhysWeight > 0.f)
362 if (!(ensure(InBoneSpaceTransforms.Num())))
369 ParentWorldTM = LocalToWorldTM;
374 int32 ParentIndex = SkeletalMesh->GetRefSkeleton().GetParentIndex(BoneIndex);
375 UpdateWorldBoneTMVR(WorldBoneTMs, InBoneSpaceTransforms, ParentIndex,
this, LocalToWorldTM, TotalScale3D);
376 ParentWorldTM = WorldBoneTMs[ParentIndex].TM;
381 FTransform RelTM = PhysTM.GetRelativeTransform(ParentWorldTM);
382 RelTM.RemoveScaling();
383 FQuat RelRot(RelTM.GetRotation());
384 FVector RelPos = RecipScale3D * RelTM.GetLocation();
385 FTransform PhysAtom = FTransform(RelRot, RelPos, InBoneSpaceTransforms[BoneIndex].GetScale3D());
388 InBoneSpaceTransforms[BoneIndex].Blend(InBoneSpaceTransforms[BoneIndex], PhysAtom, UsePhysWeight);
390 if (!bSetParentScale)
393 TotalScale3D *= InBoneSpaceTransforms[0].GetScale3D();
394 RecipScale3D = TotalScale3D.Reciprocal();
395 bSetParentScale =
true;
402 if (!(ensure(BoneIndex < EditableComponentSpaceTransforms.Num())))
410 if (!(ensure(InBoneSpaceTransforms.Num())))
414 EditableComponentSpaceTransforms[0] = InBoneSpaceTransforms[0];
418 if (bLocalSpaceKinematics || BodyIndex == INDEX_NONE || Bodies[BodyIndex]->IsInstanceSimulatingPhysics())
420 if (!(ensure(BoneIndex < InBoneSpaceTransforms.Num())))
424 const int32 ParentIndex = SkeletalMesh->GetRefSkeleton().GetParentIndex(BoneIndex);
425 EditableComponentSpaceTransforms[BoneIndex] = InBoneSpaceTransforms[BoneIndex] * EditableComponentSpaceTransforms[ParentIndex];
434 EditableComponentSpaceTransforms[BoneIndex].NormalizeRotation();
436 else if (bSimulatedRootBody)
438 EditableComponentSpaceTransforms[BoneIndex] = Bodies[BodyIndex]->GetUnrealWorldTransform_AssumesLocked().GetRelativeTransform(NewComponentToWorld);
474 bool bShouldRunPhysTick = (bEnablePhysicsOnDedicatedServer || !IsNetMode(NM_DedicatedServer)) &&
475 ((IsSimulatingPhysics() && RigidBodyIsAwake()) || ShouldBlendPhysicsBones());
479 RegisterClothTick(PrimaryComponentTick.IsTickFunctionRegistered() && ShouldRunClothTick());
492 Super::Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
494 PendingRadialForces.Reset();
497 bOldForceRefPose = bForceRefpose;
500 static const auto CVarAnimationDelaysEndGroup = IConsoleManager::Get().FindTConsoleVariableDataInt(TEXT(
"tick.AnimationDelaysEndGroup"));
502 const bool bDoLateEnd = CVarAnimationDelaysEndGroup->GetValueOnGameThread() > 0;
504 const ETickingGroup EndTickGroup = bDoLateEnd && !bRequiresPhysics ? TG_PostPhysics : TG_PrePhysics;
505 if (ThisTickFunction)
507 ThisTickFunction->EndTickGroup = TG_PostPhysics;
512 static const auto CVarHiPriSkinnedMeshesTicks = IConsoleManager::Get().FindTConsoleVariableDataInt(TEXT(
"tick.HiPriSkinnedMeshes"));
513 bool bDoHiPri = CVarHiPriSkinnedMeshesTicks->GetValueOnGameThread() > 0;
514 if (ThisTickFunction->bHighPriority != bDoHiPri)
516 ThisTickFunction->SetPriorityIncludingPrerequisites(bDoHiPri);
526 if (!IsRunningParallelEvaluation() && !bRequiresPhysics)
534 ConditionallyDispatchQueuedAnimEvents();