Download

Modular character out of sync when using Copy Pose From Mesh with physics simulation on

Hello and thank you for your attention. Sorry for the somewhat long post, but I want to provide all my fidings.

I have a modular character creator which generates characters by combining several different parts. I’m synchronizing animations with Copy Pose From Mesh, with one part serving as the master part. The whole reason I decided to go with Copy Pose From Mesh is that it allows skeletons to be extended, and theoretically works with the physics engine. Unfortunately, when I activate physics simulation on *all *the parts, the children lag behind the master by what I assume to be one frame. There seems to be no fixing it other than disabling physics simulation.

I tried moving all the slave parts to a tick group that runs after the physics engine using SetTickGroup() and it doesn’t work. I tried forcing all the slave parts to tick after the master part with AddTickPrerequisiteComponent() and it also doesn’t have any effect. What does work is disabling physics.

After re-reading the documentation, it seems Copy Pose From Mesh does not work properly when physics simulation is enabled:

This suggests I should be able to enable physics on the master part at least, as long as the child parts are not simulating. Sure enough, with only the master simulating, everything seems synchronized *provided *I move all the children to a tick group that runs after the physics calculations. I assume this is because enabling physics forces components to tick only in the ETickingGroup::TG_DuringPhysics step, so if I enable physics on everything, everything gets thrown there and the order of execution is unknown, with children that run before the master copying the last frame’s data.

In conclusion, am I correct to assume there is no way to enable physics on all the parts at once if one needs things to remain in sync? If so, what is the recommended approach to applying physics to the children? The Rigid Body node?

Thanks for your time.

Hello!
I’m fighting with exactly the same problem.
As a workaround, what I could do is to make an AnimBP:
Input Pose -> Local To Component -> RigidBody -> ComponentToLocal->Output Pose

On the rigid body, I set the Simulation Space to World Space, and setup the overlap channel ( i have this on custom ). Then I set this animBP to my hair mesh as Post Process Anim Blueprint.
This way even if the main body is physics controlled, the hair physics works.

However, this “RigidBody” physics is really unrealiable. I have a lot of stretching, many joints ignored, etc. I dont like this method, but at least it works.

If you find out how to get the normal simulated physics working, let me know!

Try master pose component.
https://youtube.com/watch?v=bE0g_djR12s
Seems to me the copy pose would lag as by the time the pose is copied from one to another the original pose has changed.

Master pose doesnt work if the slave does not have exactly the same bones as master.

And somehow my physics works now? Here is what I did, not sure if all of these are needed, but it’s working for now, so I don’t want to play with it anymore :stuck_out_tongue:

In my character.cpp constructor:

This is the skeleton mesh, coming from ACharacter


    GetMesh()->VisibilityBasedAnimTickOption = EVisibilityBasedAnimTickOption::AlwaysTickPoseAndRefreshBones;
    GetMesh()->PrimaryComponentTick.TickGroup = TG_PrePhysics;
    GetMesh()->PrimaryComponentTick.EndTickGroup = TG_PrePhysics;

This is my attached mesh component, still in constructor


        USkeletalMeshComponent* Component = CreateDefaultSubobject< USkeletalMeshComponent >( g_CharacterBodyPartNames iBodyPart ] );
        Component->SetupAttachment( GetMesh() );
        Component->VisibilityBasedAnimTickOption = EVisibilityBasedAnimTickOption::OnlyTickPoseWhenRendered;
        Component->PrimaryComponentTick.TickGroup = TG_DuringPhysics;
        Component->PrimaryComponentTick.EndTickGroup = TG_PostPhysics;
        Component->PrimaryComponentTick.AddPrerequisite( GetMesh(), GetMesh()->PrimaryComponentTick );
        Component->SetCollisionProfileName( TEXT( "ClothPhysics" ) );
        Component->SetCollisionEnabled( ECollisionEnabled::NoCollision );
        Component->PhysicsTransformUpdateMode = EPhysicsTransformUpdateMode::ComponentTransformIsKinematic;
        Component->bApplyImpulseOnDamage = false;
        Component->bReplicatePhysicsToAutonomousProxy = false;
        Component->bUpdateOverlapsOnAnimationFinalize = false;
        Component->bEnablePhysicsOnDedicatedServer = false;

This is the default, I change the collision and turn on physics on later, when I equip something and it has physics asset:


    USkeletalMeshComponent* BodyPartComponent = GetBodyPartComponent( BodyPart );
    bool bUsingMasterPose = false;

    BodyPartComponent->SetSimulatePhysics( false );
    BodyPartComponent->SetCollisionEnabled( ECollisionEnabled::NoCollision );

    BodyPartComponent->SetSkeletalMesh( NewMesh, false );

    if( BodyPartComponent->GetPhysicsAsset() )
    {
        BodyPartComponent->SetCollisionEnabled( ECollisionEnabled::PhysicsOnly );
        BodyPartComponent->SetSimulatePhysics( true );
    }

And it… works? No more lagging behind. Probably the TickGroup and EndTickGroup settings fixed it. “ClothPhysics” is just a collision profile I made so it does not collide with the pawn’s capsule collider, and so on.
Hope this helps

Nevermind, it doesn’t work, just reduced the lag a little. At fast movement it still detaches and it makes me a very sand panda.

if you have a character with different skeletal meshes, I found the only way to get the anims work in sync is to disable and re-enable them (in my case horse + rider + bow) by NoSkeletonUpdate (set to true, use a short e.g. 0.1s Delay, then set to false).

I struggled same problem.
At fast animation or movement it does not detaches from source mesh any more.
Try this. I hope it helps.



ChildMesh->AddTickPrerequisiteComponent( ParentMesh );


https://docs.unrealengine.com/en-US/…ers/index.html

https://docs.unrealengine.com/en-US/…ing/index.html