This issue is present both in Unreal 5.4.3 and 5.5.4.
It seems that the OrientationWarping Anim Node does not support to take as input an FCSPose that contains some bone transforms stored in component space.
Looking at the code, all the transformations applied by the node are set directly in Component Space using FCSPose<FCompactPose>::SetComponentSpaceTransform() which does not make sure that the children of the modified bones are affected by their parent’s new transform.
When the pose does not contain any Component Space transform, all the bones are expressed locally to their parent so the new transform of the root bone is implicitly applied to all its descendants. However, if a bone is stored in component space, the Orientation Warping node will not update its transformation when rotating the root, thus leaving it with the exact same component space transform, altering the pose.
In the repro project, a Copy Bone node is used to express a few bones in component space, including the pelvis. When the Orientation Warping is evaluated, the transform of the root is modified but it not applied to the pelvis, which cause the whole character to keep its original orientation. As the IK feet and Spine bones are modified in the same way, similar issues can occur to their children if they are expressed in component space.
I was able to patch the node using FCSPose<FCompactPose>::SafeSetCSBoneTransforms() to modify the root bone in order to apply the transformation to its descendants in component space. For the Spine and IK Feet I add them to the OutBoneTransforms instead, in order to apply the transformation all at once.
Steps to Reproduce
Steps to reproduce this issue :
- Open the repro project
- Open the ABP_OrientationWarpingRepro asset
The blueprint contains a very basic “motion matching” setup simply matching a single run animation and applying an Orientation Warping inside the MotionMatching node’s subgraph to emulate a trajectory not aligned with the animation. Everything is working properly, the character’s feet are facing the trajectory and the spine is oriented in the other way around to compensate for the root rotation.
- Dive into the AnimGraph > AnimationBlendStackGraph_0
- Plug the CopyBone node between the LocalToComponent and Orientation Warping nodes.
- Compile the Blueprint
You should see how the animation offsets between the two setups. More precisely, the pelvis bone keeps its initial rotation, making the feet not match the wanted trajectory and making the spine rotate in the opposite way (compensating for a rotation that is not applied).
Here is a .patch file showing how I fixed the code.
Hi, thanks for reporting this. I talked with the dev team about the implementation and it sounds like the reason that it was done as you’ve noted (by just calling SetComponentSpaceTransform on the output transform pose directly) was to avoid the performance hit of having to convert between local and component space repeatedly. But it does mean that the kind of setup that you have where another bone in the pose is already in component space will break.
A full fix for this is going to take a bit of thinking about. Ideally we would use OutBoneTransforms for all the bones that are being modified by the node so that they could be blended correctly onto the output pose (in FCSPose<PoseType>::LocalBlendCSBoneTransforms which is called later from FAnimNode_SkeletalControlBase::EvaluateComponentSpace_AnyThread). But this could require a lot of space switching of the transforms. Your suggested change to use SafeSetCSBoneTransforms directly on the root avoids that, but the downside is that I don’t think that will blend correctly if the alpha value changes (which is broken anyway in the current implementation).
The alternative here is to change the graph. In between the CopyPose and OrientationWarping nodes, you could add ComponentToLocal and LocalToComponent conversion nodes. That would convert the transforms output from the Copy Pose node all back into local space and then put them back into a FCSPose so they could be operated on by the orientation warping as-is. But again the space conversion for that is going to be somewhat wasteful. So I think your changes are a good workaround for this issue for now.