This Tutorial will guide you into loading a ReadyPlayerMe character at runtime and applying a Mixamo Animation over it (included root motion, if required).
The Animation is converted to a glb file using Blender, so you can load animations at runtime too.
Everything will be done with Blueprints but you can obviously accomplish the same results with C++ too.
We will not use the provided glTFRuntimeAssetActor but we will load everything manually to have full control (and better understanding) over the workflow.
Note: those steps are pretty advanced and generally you do not need to follow them if the animations are fully GLTF compliant and compatible with your mesh skeleton.
Mixamo Note: based on the selected character you may end with a different skeletal structure. Using the "David" character is highly suggested (I always had good results with it ;)
This is simple, we are going to use the LoadSkeletalMeshRecursiveAsync
to compact the whole RPM Avatar in a single SkeletalMesh (instead of a hierarchy of multiple SkeletalMeshes) and we assign it to an empty Character placed in the level:
The result is good but no "cool":
- The root bone is mapped to "Hips" instead of the middle of the feet
- The pivot of the SkeletalMesh does not map to the base of the Character's CapsuleCollision (it is flying!)
Let's configure the glTFRuntime Skeleton loader to automatically add a root bone:
Now the result is way better:
The root bone is "valid" (no more red bone in the Skeleton Editor)
We are going to fix the "flying avatar issue" by using the model bounds.
Be prepared for a bit of spaghetti:
Thanks to the bounds height (the Z value, remember to break/split the Extent bounds pin of the GetBounds node) we can set the capsule 'Half Height' and move the SkeletalMeshComponent to the right vertical offset
Ok, we are good. Time for Mixamo!
Go to Mixamo and download your favourite animation. We are going to use the "manga-like" Run:
Download it as FBX and ensure to not export the skin (we are just interested in skeleton structure and animation curves)
Now import the FBX in blender (ensure to set the "Automatic Bone Orientation" flag):
And now slide the animation timeline to check that everything is fine (it is obviously hard to understand what is going on given that we have only bones as visual reference).
If your animation has root motion, ensure that the skeleton moves too while sliding the timeline.
Now export the object as gltf/glb from blender (you can use the default export settings) and prepare for the next step.
Add a new pin to the Sequence node, load the GLTF file and extract the animation from it:
Oops! something went wrong:
The bones names of the Mixamo asset do not match the bones names of the RPM Avatar :(
This is a pretty advanced procedure you will generally do in C++. Lucky enough the difference is just the '''mixamorig:'' (or '''mixamorig10:''' if you are using David) prefix in each bone, so our remapping function will be super simple (and we can do it with a Blueprint):
The Curve Remapper pin allows you to define a delegate/event/filter to rename an animation curve (that is generally named as the bone to which transformations are applied). Ensure to use the "Create Event" node when connecting the red (event) pin (we cannot use the "Add Custom Event" node as our function needs to return a value).
In the "Create Event" node, select the "Create a Matching Function" option to create and access you "remapper" function
Let's modify it to remove the '''mixamorig:''' prefix (or mixamorig10, or whatever is the bone prefix for the asset):
The errors in the Output log should now disappear, so we can play our animation by setting the AnimationData structure of the SkeletalMeshComponent and its AnimationMode:
If we hit play we will see a pretty messy situation with our Avatar being dismembered (or something similar...)
Retargeting is the process of converting a bone transformation based on a pose, to another one based on a different pose.
The problem we are facing is that the Mixamo animation curves have been built for a specific pose (different from the RPM Avatar).
Lucky enough we can easily retarget animations in glTFRuntime, but before doing this we need to address the scaling of the animation (unfortunately when exporting from an FBX, blender will scale everything by 100, so we set the SceneScale value to '1')
Let's try again:
Ok, visible, but definitely wrong, let's retarget the animation!
By connecting the RetargetTo pin to the Skeleton object of the SkeletalMesh (the RPM one) the animation curves will be converted for the new skeleton:
we can now hit play again:
There is still a problem with the arms: they cross in a pretty weird way.
This is caused by the mixamo animation being created for a model in T-Pose, while the RPM Avatar is in A-Pose.
The fix is again pretty easy, we can add a "transformation" to every relevant curve in our animation to address the difference in default poses:
Hit play again:
Great, the arms are fixed and theoretically if you animation has no root motion, you could end your workflow here.
Currently the root motion in our animation is still mapped to the Hips curve, let's move it to the "root" bone by editing our curve remapper function (the one we previously created for removing the "mixamorig:" prefix):
Whenever a "translation" curve is named "Hips", we move it to the "root" one.
We can finally enable "RootMotion" and "Anim First Frame" LockMode in our animation
and we can turn root motion "on" in the AnimInstance:
- As already said this is an advanced approach mainly useful for showing advanced glTFRuntime features
- Some of the Mixamo characters works bad given that their bone pose references are way different from the RPM skeleton
- You can end your workflow at step 7 if you do not need root motion support