Playing an animation for only one frame in the game ?

Hey everyone,

I want a socket to be at the center of the hand of my skeletal mesh in order to hold a weapon.

But i am using several different skeletons, and several different meshes for the each skeleton, so i need an automatic procedure to relocate the socket everytime i change the mesh or skeleton in game (different meshes have different proportions, and different skeletons have different bones orientations).

So i need to know both the direction of the hand and the direction of the palm of the hand (in the hand bone frame of reference) to relocate the socket.

Unfortunately, if it is easy to know the direction of the hand (HandBone->GetTranslation()), as far as i understand it is not possible to know the direction of the palm as it is up to a 360 rotation around the direction of the hand.

Btw, if anyone knows a way to get the direction of the palm easily, you’ll get my eternal gratitude :slight_smile:

So here is the workaround i made up:

  • load the TPose, so i know the palm is looking downward in the world frame of reference
  • then express the FVector::UpVector from world frame of reference to hand bone frame of reference (using SkeletalMeshComponent::TransformToBoneSpace).
    This gives me, up to a sign, the direction of the palm in the hand bone frame of reference.

It works very well, but i don’t want the TPose to be my default animation.

So i need to do the following:

  • load the TPose
  • compute the palm direction in the hand bone frame of reference
  • load the default animation back

The problem is that i can’t find a way to load the TPose temporarily.

This sort of pseudo code wont work:


// when this function is called, the default animation is loaded and playing
void MyActor::ChangeSkeletalMesh(NewSkeletalMesh)
{
MySkeletalMeshComponent->SetSkeletalMesh(NewSkeletalMesh);

LoadAnimation(Tpose);
PlayAnimation(TPose);

<compute palm direction>

LoadAnimation(DefaultAnimation);
PlayAnimation(DefaultAnimation);
}

Where

  • LoadAnimation is a function that dynamically loads an animation asset using LoadObject and given the animation name as a FString
  • the computation of the palm direction involves Skeletal3DMesh->RefSkeleton.GetRefBonePose()
  • PlayAnimation is a function that plays an animation using SkeletalMeshComponent::PlayAnimation function.

My problem is that this setup works only when the default animation is the TPose, but doesn’t work with any other default animation.

More precisely, it works when the skeleton is changed, but doesn’t when the skeletal mesh is changed on the same skeleton: the palm direction is computed using the default animation, as if the TPose was not loaded/played.

So is there a way to load an animation (here the TPose) only for one frame, or any subliminal fraction of time ?

Of course, if anyone needs, i can provide the full code, it’s just much longer.

Thanks

Cedric

hmmm, one thing is not clear here, let’s say i run this code:


Skeletal3DMeshComponent->SetSkeletalMesh(Skeletal3DMesh);
const FReferenceSkeleton & ThisReferenceSkeleton = Skeletal3DMesh->RefSkeleton;
const TArray< FTransform > & ThisTransformArray = ThisReferenceSkeleton.GetRefBonePose();

Anyone know what FTransform i will get in my array ?

  • Tranforms corresponding to the skeleton reference pose ?
  • Transforms corresponding to the skeleton currently playing animation ?

It would seem that it’s the second answer, because when i change the skeleton i get good results (the new skeleton is in TPose by default), and when i change only the skeletal mesh on the same skeleton, i get transforms from the currenly playing animation.

So my question becomes: is there a way to either

  • reset the RefSkeleton pose/transforms ?
  • force the reloading of the default RefSkeleton when changing the skeletal mesh on the same skeleton ?

Thanks

Cedric