Download

Going from ragdoll (simulate physics on the mesh) to animation always goes through T-Pose/Bindpose

Hello,

Sorry if this is the wrong place to post this in, I’m unsure as to where this thread belongs. That being said, I have a small issue regarding playing an animation after turning simulate physics on a mesh off. It always goes through the T-Pose first. Here’s an example of the issue (ignore the rotation):

https://i.makeagif.com/media/9-22-2017/2u05aw.gif

All I’m doing in that example is calling my ***StartRagdoll() ***and two seconds later my ***EndRagdoll() ***functions. As you can see, as soon as ***EndRagdoll() ***is executed, the character goes into T-Pose and THEN goes into the specified animation. I currently have the start blend on the PlaySlotAnimationAsDynamicMontage() to play the get-up animation set to 0, and if I set it any higher, it’ll start at T-Pose and then it will blend over the specified amount of time.

Here are my function definitions:
StartRagdoll() [SPOILER]



// enable CCD on root body to avoid passing through surfaces
    if (GetMesh()->GetBodyInstance() != nullptr)
    {
        GetMesh()->GetBodyInstance()->bUseCCD = true;
    }

    GetMesh()->SetAllBodiesNotifyRigidBodyCollision(true);
    GetMesh()->SetCollisionEnabled(ECollisionEnabled::QueryAndPhysics);
    GetMesh()->UpdateKinematicBonesToAnim(GetMesh()->GetComponentSpaceTransforms(), ETeleportType::TeleportPhysics, true);
    GetMesh()->SetSimulatePhysics(true);
    GetMesh()->RefreshBoneTransforms();
    GetMesh()->DetachFromComponent(FDetachmentTransformRules::KeepWorldTransform);
    RootComponent = GetMesh();
    GetMesh()->bGenerateOverlapEvents = true;
    GetMesh()->bShouldUpdatePhysicsVolume = true;
    GetCapsuleComponent()->SetCollisionEnabled(ECollisionEnabled::NoCollision);
    GetCapsuleComponent()->DetachFromComponent(FDetachmentTransformRules::KeepRelativeTransform);
    GetCapsuleComponent()->AttachToComponent(GetMesh(), FAttachmentTransformRules::KeepWorldTransform);

    GetCharacterMovement()->StopActiveMovement();
    GetCharacterMovement()->Velocity = FVector::ZeroVector;    


[/SPOILER]

***EndRagdoll() ***
[SPOILER]



    GetCapsuleComponent()->DetachFromComponent(FDetachmentTransformRules::KeepWorldTransform);

    RootComponent = GetCapsuleComponent();

    GetMesh()->bGenerateOverlapEvents = false;
    GetMesh()->bShouldUpdatePhysicsVolume = false;

    // Adjust capsule height
    FVector AdjustedLoc = GetActorLocation() + FVector(0.0f, 0.0f, GetCapsuleComponent()->GetScaledCapsuleHalfHeight());
    GetWorld()->FindTeleportSpot(this, AdjustedLoc, GetActorRotation());
    GetCapsuleComponent()->SetWorldLocation(AdjustedLoc);

    GetCapsuleComponent()->SetCollisionEnabled(ECollisionEnabled::QueryOnly);

    GetMesh()->SetSimulatePhysics(false);
    GetMesh()->AttachToComponent(GetCapsuleComponent(), FAttachmentTransformRules::SnapToTargetNotIncludingScale);
    GetMesh()->AddLocalOffset(FVector(0, 0, -100));
    GetMesh()->SetRelativeRotation(FRotator(0.f, -90.f, 0.f).Quaternion());

    GetMesh()->GetAnimInstance()->PlaySlotAnimationAsDynamicMontage(GetUpAnimation, "DefaultSlot", 0.f);


[/SPOILER]

As you can see I’m not really doing anything special. If I had to guess, the reason why it goes over T-Pose is because when it tries blending it attempts to get the “current” animation that it will blend from, and there probably isn’t one after coming out of ragdoll or something like that. Even if I **don’t **play any animation, before the Mesh goes back to its idle animation it stutters through the T-Pose as well. Is there any way to blend between the current ragdoll pose to the new (get-up) animation? Or is it only possible to blend from animation to animation? What I would like to do is have the mesh smoothly begin the animation from whatever random position the mesh has taken as a result of hitting the ground while in ragdoll.

Thank you for any help!

  • J

Finally fixed it.

I went frame-by-frame and noticed that the issue happens on a single frame, the very frame EndRagdoll() is called. So I played the animation, delayed for .02, **then **ran EndRagdoll() and it finally worked.

Add this code to manually refresh the mesh’s animation, so you don’t have to use a delay. I ran it right after PlaySlotAnimationAsDynamicMontage(): [SPOILER]


    
GetMesh()->UpdateKinematicBonesToAnim(GetMesh()->GetComponentSpaceTransforms(), ETeleportType::TeleportPhysics, true);
GetMesh()->GetAnimInstance()->UpdateAnimation(GetWorld()->GetDeltaSeconds, false);
GetMesh()->RefreshBoneTransforms();


[/SPOILER]

I still have a big issue, however, which is that I can’t blend from the ragdoll to the animation. I will be making a new thread in the animation section but if anyone knows please let me know.

Edit: Got everything working. Use ***GetMesh()->GetAnimInstance()->SavePoseSnapshot() ***to save a snapshot that you can access from your AnimBP (and blend for it) while in ragdoll.

-J