Search Unity

  1. Unity 6 Preview is now available. To find out what's new, have a look at our Unity 6 Preview blog post.
    Dismiss Notice
  2. Unity is excited to announce that we will be collaborating with TheXPlace for a summer game jam from June 13 - June 19. Learn more.
    Dismiss Notice

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

Discussion in 'Animation' started by superkerokero, Sep 30, 2022.

  1. superkerokero

    superkerokero

    Joined:
    Dec 9, 2015
    Posts:
    8
    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:


    Code (CSharp):
    1.         public void ProcessRootMotion(AnimationStream stream)
    2.         {
    3.             stream.velocity = Vector3.zero;
    4.             stream.angularVelocity = Vector3.zero;
    5.         }
     
  2. superkerokero

    superkerokero

    Joined:
    Dec 9, 2015
    Posts:
    8
    Original animation gif:
     

    Attached Files:

  3. superkerokero

    superkerokero

    Joined:
    Dec 9, 2015
    Posts:
    8
    Set velocity and angularVelocity to zero:
     

    Attached Files:

  4. dyno_sam

    dyno_sam

    Joined:
    Jan 14, 2020
    Posts:
    2
    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
    Code (CSharp):
    1. ProcessRootMotion(AnimationStream stream)
    Any progress on this @superkerokero?
     
  5. superkerokero

    superkerokero

    Joined:
    Dec 9, 2015
    Posts:
    8
    @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.
     
  6. VirtusH

    VirtusH

    Joined:
    Aug 18, 2015
    Posts:
    95
    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.
     
    Duelz96 likes this.
  7. Duelz96

    Duelz96

    Joined:
    May 22, 2020
    Posts:
    1
    You and me both brother. Any update on how to do this?
     
  8. VirtusH

    VirtusH

    Joined:
    Aug 18, 2015
    Posts:
    95
    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)
     
  9. SolarianZ

    SolarianZ

    Joined:
    Jun 13, 2017
    Posts:
    245