[Animation C# Jobs] How to properly modify root motion in IAnimationJob.ProcessRootMotion()

IAnimationJob provides a method called “ProcessRootMotion”, as its name suggests, it’s supposed to be used to process animation’ s root motion.

ProcessRootMotion() has AnimationStream as the parameter.
AnimationStream has properties of “rootMotionPosition” and “rootMotionRotation”, but these are READ_ONLY, meaning you can’t modify them.
In addition, AnimationStream provides “velocity” and “angularVelocity”, which are supposed to be avatar’s velocities. These are writable, but I can’t figure out how to use them to modify root motion that comes with an animation.

Example 1.
The character and animation is taken from mixamo.com.
In this case, the animation is “capoeira”, which has root motion that moves the character around.
Setup the character with custom animation c# job like this and modify the velocity and angular velocity to zero. The expected result would be that the character stops moving around.
But character’s trajectory changes to a straight line, still moving.

Original animation:

Set velocity and angularVelocity to zero:

        public void ProcessRootMotion(AnimationStream stream)
        {
            stream.velocity = Vector3.zero;
            stream.angularVelocity = Vector3.zero;
        }

Original animation gif:

8478824--1127096--ezgif.com-gif-maker.gif

Set velocity and angularVelocity to zero:

8478830--1127099--zero.gif

I’m trying to make an Animation Rigging constraint for full-body tracking and have the same issue with trying to modify the root motion in ProcessRootMotion(AnimationStream stream)
Any progress on this @superkerokero ?

@dyno_sam
It seems that you can’t modify/overwrite the root motion baked into animations inside “ProcessRootMotion()”. This function only allows you to add some custom processings to the baked root motion, such as adding a vector to the already existing velocity.

In order to modify the root motion itself, you have to use OnAnimatorMove, which is a monobehaviour message that only works with an Animator component attached to the same gameobject. The baked root motion can be accessed through Animator.deltaPosition and Animator.deltaRotation, both values are modifiable.

You have to be joking?

There is zero documentation on this…

I’m trying to add some root motion rotation and just hitting a brick wall of bugs and glitches.

1 Like

You and me both brother. Any update on how to do this?

I can’t remember what exactly I was doing, but I know I ended up writing a system to handle TransformAccessArrays for all of my animals and their bones. I also made my own value transform system, and had jobs where right after animation is done I read all the transforms I care about in a burst job, do whatever I want, then write the modified ones back in another burst job before the end of the frame.

This all made it so I could write a full IK solution that operated on my value transform stuff in Burst, I had a lot of requirements and reasons for doing it this way.

Maybe I could’ve found a way to use Animation Jobs, but they seemed like a PITA.

DIY is probably not what you want to hear, but I tried a bunch of stuff and couldn’t get anything to work the way I wanted.

I did have this exchange the with developer of Animancer (cool guy) when I was trying to figure this out. Maybe something in here could be of help, feel free to borrow math from my code or whatever.
https://github.com/KybernetikGames/animancer/issues/302

Honestly what I would try is to just track the transformation difference each frame, and just update the transform manually right after animations are done. (I did the timing part with a custom playerloop, but you can get pretty close with a negative execution order I bet)

I encountered the same problem. It was caused by a bug in Unity.

Here are the details and my solution: