Disable MoverComponent when skeletal mesh is fully simulated by physics

Hello, we are using Mover for movement (the same way as used in the GASP project), but it seems it should be “turned off” when the character enters full body ragdoll (see the “steps to reproduce”). Disabling the mover or its tick does not do anything, as can be seen from the callstack, the move is actually triggered from UMoverStandalonLiaisonComponent. Disabling its tick function like so:

Liaison->RegisterComponentTickFunctions(false);does resolve the issue, however, it then fails the check on the first line of

UActorComponent::RegisterAllComponentTickFunctions(bool bRegister)
{
     check(GTestRegisterComponentTickFunctions == NULL);
...
}

Is there some recommended way to handle this?

Steps to Reproduce

  1. have character with a skeletal mesh component and UMoverComponent for movement
  2. set the whole mesh to be simulated by physics, for example add this event handler to the BP of the character:
  3. start Play In Editor (any level), press E to turn on the physics
Observe that errors "Attempting to move a fully simulated skeletal mesh {0}. Please use the Teleport flag

are written to the console every frame from callstack like this:

USkeletalMeshComponent::MoveComponentImpl(const UE::Math::TVector<…> &, const UE::Math::TQuat<…> &, bool, FHitResult *, EMoveComponentFlags, ETeleportType) SkeletalMeshComponent.cpp:5217
[Inlined] USceneComponent::MoveComponent(const UE::Math::TVector<…> &, const UE::Math::TQuat<…> &, bool, FHitResult *, EMoveComponentFlags, ETeleportType) SceneComponent.h:1717
USceneComponent::SetRelativeLocationAndRotation(TVector<…>, const UE::Math::TQuat<…> &, bool, FHitResult *, ETeleportType) SceneComponent.cpp:1754
USceneComponent::SetRelativeTransform(const UE::Math::TTransform<…> &, bool, FHitResult *, ETeleportType) SceneComponent.cpp:1907
UMoverComponent::FinalizeFrame(const FMoverSyncState *, const FMoverAuxStateContext *) MoverComponent.cpp:386
UMoverStandaloneLiaisonComponent::TickApplySimulationState(float) MoverStandaloneLiaison.cpp:404
[Inlined] FMoverStandaloneApplyStateTickFunction::ExecuteTick::__l2::<lambda_1>::operator()(float) MoverStandaloneLiaison.cpp:495
[Inlined] FActorComponentTickFunction::ExecuteTickHelper(UActorComponent *, bool, float, ELevelTick, const <lambda_1> &) Actor.h:4924
FMoverStandaloneApplyStateTickFunction::ExecuteTick(float, ELevelTick, Type, const TRefCountPtr<…> &) MoverStandaloneLiaison.cpp:493
[Inlined] FTickFunctionTask::DoTask(Type, const TRefCountPtr<…> &) TickTaskManager.cpp:334
TGraphTask::ExecuteTask() TaskGraphInterfaces.h:710
UE::Tasks::Private::FTaskBase::TryExecuteTask() TaskPrivate.h:518
[Inlined] FBaseGraphTask::Execute(TArray<…> &, Type, bool) TaskGraphInterfaces.h:493
FNamedTaskThread::ProcessTasksNamedThread(int, bool) TaskGraph.cpp:799
FNamedTaskThread::ProcessTasksUntilIdle(int) TaskGraph.cpp:698
[Inlined] FTaskGraphCompatibilityImplementation::ProcessThreadUntilIdle(Type) TaskGraph.cpp:1439
FTaskGraphCompatibilityImplementation::ProcessUntilTasksComplete(const TArray<…> &, Type, const TFunction<…> &) TaskGraph.cpp:1577
FTickTaskSequencer::ReleaseTickGroup(ETickingGroup, bool, TArray<…> &) TickTaskManager.cpp:1040
FTickTaskManager::RunTickGroup(ETickingGroup, bool) TickTaskManager.cpp:2133
[Inlined] UWorld::RunTickGroup(ETickingGroup, bool) LevelTick.cpp:784
UWorld::Tick(ELevelTick, float) LevelTick.cpp:1721
UEditorEngine::Tick(float, bool) EditorEngine.cpp:2175
UUnrealEdEngine::Tick(float, bool) UnrealEdEngine.cpp:531
FEngineLoop::Tick() LaunchEngineLoop.cpp:5834
[Inlined] EngineTick() Launch.cpp:60
GuardedMain(const wchar_t *) Launch.cpp:192
LaunchWindowsStartup(HINSTANCE__ *, HINSTANCE__ *, char *, int, const wchar_t *) LaunchWindows.cpp:266
WinMain(HINSTANCE__ *, HINSTANCE__ *, char *, int) LaunchWindows.cpp:334

Hey there,

I want to preface by saying we’ll answer the specific question you have, but there is a much better recommended approach that we’ll be releasing as an example with the update to the Game Animation Sample project. We’ve been making specific improvements to Mover and some physics workflows that we’ll be showing soon.

For your question, there isn’t a great way to handle it other than disabling individual tick functions.

FindTickFunction( EMoverTickPhase eachPhase) -> SetTickFunctionEnable( false)That said, this isn’t the approach we would recommend.

Instead, we would recommend creating a “ragdoll” movement mode and leaving the tick intact. This is the approach we’re taking for the upcoming release and is better for network play. One of the key issues is that when going full ragdoll, you often want the capsule of the character to follow ragdoll and have a movement mode that handles having the capsule follow the pelvis (or whatever bone you like) with UMovementUtils::TrySafeMoveAndSlideUpdatedComponentNoMovementRecord.

Also, on the skeletal mesh, you’ll want to look into changing the property PhysicsTransformUpdateMode to ‘Component Transform Is Kinematic’. This will ensure that your root follows that capsule as well, making sure that all of your components are in the right spot during ragdoll simulation and in prep for something like a getup.

I hope this helps you and also highlights the directions that we’re looking at. I recommend being on the lookout for the 5.8 update of Mover and the Game Animation Sample Project for all of this.

Dustin

Also, first preview of 5.8. should be in May, is that still correct? I need to get this working by the end of June, so if the examples and updates will be available in May maybe its better I just wait, but if not, I’ll keep trying.

No, the Game Animation Sample Project tends to lag behind as well, so I’ll translate as much as I can to what we’re doing, and we’ll get you sorted out.

For our “Ragdoll” movement mode, we implement everything in blueprint, so I’ll share what we’ve done so far (note: that it’s subject to change on the release). I’m having issues with inline image uploads, so I’ll attach the screenshots as a separate post and talk to them.

For our mode, we just do two things.

  1. Override the SimulateTick with a movement mode that is derived from the BaseMovementMode.
  2. We have, on the Skeletal Mesh PhysicsTransformUpdateMode, always set it to ComponentTransformIsKinematic and it is always running in no matter the mode.

We don’t disable anything, and we don’t stop the mover from ticking. We project the pelvis’s motion onto the capsule through that pelvis offset, and with the ComponentTransformIsKinetic, we link the root to the capsule. That’s pretty much it. Note that in the images, we are using sweep, and teleport is set to None to perform the move. We treat the ragdoll movement as the source. We do have animations playing on the character, but they’re really just pose-based blend spaces we blend into the ragdoll, so unless you’re doing anything else, the root should move to where your capsule is.

We might need to share more of your setup to get a clearer picture to help you out. Let me know.

Dustin

Hello,

I’ve tried to implement a custom movement mode that ignores input

void URagdollMode::GenerateMove_Implementation(const FMoverTickStartData& StartState, const FMoverTimeStep& TimeStep, FProposedMove& OutProposedMove) const
{
	OutProposedMove = FProposedMove();
}

and in SimulationTick_Implementation moves the capsule to pelvis using TrySafeMoveAndSlideUpdatedComponentNoMovementRecord

(with both the sweep and slide bools set to false and teleport type to TeleportPhysics). The capsule is repositioned correctly by this, but the UMoverStandaloneLiaisonComponent is still trying to move the skeletal mesh each frame which outputs the same warning as before. I’ve tried detaching the skeletal mesh from the capsule, calling Deactivate on both the mover and the liaison, but it does not seem to help. Setting the PhysicsTransformUpdateMode to ‘Component Transform Is Kinematic’ as you suggested gets rid of the warning, but causes the root of the skeletal mesh to be moved to 0,0 (maybe because there is no animation once I turn ragdoll on?) while the rest of the body remains where it was ragdollized.

Are there perhaps some necessary Mover updates among those you are preparing to make this work, or is it more likely that there is something wrong/missing in my setup?

Also, first preview of 5.8. should be in May, is that still correct? I need to get this working by the end of June, so if the examples and updates will be available in May maybe its better I just wait, but if not, I’ll keep trying.

Attaching the screenshots Dustin mentioned on his behalf

Thank you, it does work in the end when I set it up exactly as you have it. Having teleport physics set to None is key (I had it at None at first, but probably had something else wrong, changed it and never tried to change back).

Thank you for your help.