UPoseableMeshComponent one frame behind physics bodies

I’m having an issue with a ragdoll skeletal mesh being one frame behind.

My setup…

  • I have a custom actor class (ABipedActor) that creates a UPoseableMeshComponent to render the character’s mesh.
  • Separate rigidbody actors that are the physics driven actor bodies (ARigidbodyActor) which are joined with constraints to define the physical.
  • ABipedActor::Tick updates the PMC’s bone space transforms based on the above RigidbodyActors’ transforms.

The problem is that when the poseable mesh renders, it’s pose is one frame behind the physics bodies. You can see here the detachment between the hand (rigidbody static mesh) and arm (part of the biped’s poseable mesh)…

Clipboard01.jpg

I am setting the biped’s tick group to (in theory) be at the end of the tick update.


PrimaryActorTick.bCanEverTick = true;
PrimaryActorTick.TickGroup = TG_PostUpdateWork;
PrimaryActorTick.EndTickGroup = TG_PostUpdateWork;

And then inside the biped’s Tick…


if ( PoseableMeshComponent && biped ) {

    if ( MaulBody * body = biped->hip ) {

        int n = body->bones;
        n = Min( n, PoseableMeshComponent->BoneSpaceTransforms.Num() );

        for ( int i = 0; i < n; i++ ) {
            if ( MaulBody * bone = body->bones* ) {
                auto & t = PoseableMeshComponent->BoneSpaceTransforms*;
                if ( i > 0 ) {
                    t = bone->unrealRigidbody->GetActorTransform() * body->unrealRigidbody->GetActorTransform().Inverse();
                } else {
                    t = bone->unrealRigidbody->GetActorTransform();
                }
            }
        }

    }

    PoseableMeshComponent->MarkRefreshTransformDirty();

}



I found a solution on my end. Based on looking inside the UPoseableMeshComponent source code, after updating the BoneSpaceTransforms, I’m now using RefreshBoneTransforms (instead of where I had MarkRefreshTransformDirty) and everything us synced up nicely.


PoseableMeshComponent->RefreshBoneTransforms( nullptr );

UPoseableMeshComponent::RefreshBoneTransforms ignores the update function (so just give it a null), but does all this internally which now that it’s happening the rendering is no longer one frame behind. Wahoo! :slight_smile:


// We need the mesh space bone transforms now for renderer to get delta from ref pose:
FillComponentSpaceTransforms();
FinalizeBoneTransform();

UpdateChildTransforms();
UpdateBounds();
MarkRenderTransformDirty();
MarkRenderDynamicDataDirty();

bNeedsRefreshTransform = false;