Search Unity

Make root motion in animation clip

Discussion in 'Animation' started by TMPxyz, Jun 9, 2014.

  1. TMPxyz

    TMPxyz

    Joined:
    Jul 20, 2012
    Posts:
    766
    Hi, I have a question on apply root motion.

    I have a model in generic rig with 'Hips' as the root node.
    and I made an animation with Unity Animation Window that moves the hips.

    Now I want the translation on hips to be used by Animator's 'Apply Root Motion';

    I checked other imported animation, they have animated properties of 'Animator.Motion T' and 'Animator.Motion Q', the curves looks similar with 'Hips'.

    So, my question is, if I duplicate the 'Hips.localPosition' and 'Hips.localRotation', make two animated properties of 'Animator.Motion T' and 'Animator.Motion Q' with script, will the Animator handle the Root motion properly?
    If true, will blending multiple animations affect the correctness?

    3.jpg
     
  2. TMPxyz

    TMPxyz

    Joined:
    Jul 20, 2012
    Posts:
    766
    Well, seems work.

    But I'm not yet sure if it works in all situations.
    Hope Mecanim.Dev could give some inside details.
     
  3. Mecanim-Dev

    Mecanim-Dev

    Joined:
    Nov 26, 2012
    Posts:
    1,675
    Yes that exactly how mecanim does it under the hood. The curve for the root node are copied from the specified transform in the tools to properties Motion.T and Motion.Q. So it should work perfectly.

    Best regards,
    Sonny
     
  4. TMPxyz

    TMPxyz

    Joined:
    Jul 20, 2012
    Posts:
    766
    Well, Thank goodness.

    If this does not work out, I'll have to read the code of RootMotionController asset.

    Really love it. Saved me quite some time.
     
  5. TMPxyz

    TMPxyz

    Joined:
    Jul 20, 2012
    Posts:
    766
    Hi, I have encountered some small problems on the animation clip.

    I have duplicated the root node's P and R curves to MotionT and MotionQ.
    The root motion function works well,

    but when I look at the clip, it's filled with keyframes.
    Although the result is alright, this would be not very easy for further editing work.

    I think I haven't touched other curves though...

    Could someone tell me how to prevent such keyframe flood? Is there something I'm doing wrong?

    @Mecanim.Dev

    BEFORE:
    4.jpg
    AFTER: 5.jpg
     
  6. Mecanim-Dev

    Mecanim-Dev

    Joined:
    Nov 26, 2012
    Posts:
    1,675
    Unfortunally no there is nothing you can do.

    What going on is that when we create the mecanim animation clip we have to resample the whole clip and for each sample we convert the transform animation curve to muscle animation curve, this is the retargeting step. This is why you see so many keyframe,

    That been said, you still have access to the transform curve in the animation clip, if you need to edit them you should edit the transform animation curve and then reprocess your clip to generate mecanim root motion.

    Sonny
     
  7. TMPxyz

    TMPxyz

    Joined:
    Jul 20, 2012
    Posts:
    766
    Hi, Sonny,

    I've made a last try on switching form AnimationClip.SetCurve to AnimationUtility.SetEditorCurve, and it works, even automatically handled the update of Animation TreeView.

    Maybe it's because I'm using Generic clip not muscle clip? No matter what, the end justifies the means :)

    Thanks for your replies, it's great to hear some inner details.

    6.jpg
     
    Mecanim-Dev likes this.
  8. nigredo_tori

    nigredo_tori

    Joined:
    Jul 11, 2014
    Posts:
    3
    Hello. Does root motion require a rig and a model? I've got a simple sprite character, and I'm trying to tie its movement to animation, but to no avail.

    I set MotionT components as follows:

    Code (CSharp):
    1. var binding = new EditorCurveBinding();
    2. binding.path = "MotionT.x";
    3. binding.type = typeof(Animator);
    4. binding.propertyName = propName;
    5. AnimationUtility.SetEditorCurve(clip, binding, curve);
    Curve is the root object's corresponding position component's animation curve.

    The curves are displayed in Animation window Curve mode, but their value is always zero in properties panel. No root motion is applied.

    All "Based Upon"'s of the clip are set to Root Node Position, changing them to other values doesn't seem to work. All "Bake Into Pose" checkboxes are turned off.
    I also tried few other binding paths, like "Motion T" or "m_MotionT", neither worked.
     
  9. Mecanim-Dev

    Mecanim-Dev

    Joined:
    Nov 26, 2012
    Posts:
    1,675
    You did invert two parameter,

    binding.path = "";
    binding.propertyName = "MotionT.x";

    We do have a demo with a sprite character and some root motion but unfortunately I can't find it.
     
    nigredo_tori likes this.
  10. nigredo_tori

    nigredo_tori

    Joined:
    Jul 11, 2014
    Posts:
    3
    Thank you for fast reply.

    Yes, I did invert these parameters, I suppose it happened when editing code before publication, since they're not inverted in the source.
    Here's the full method:
    Code (CSharp):
    1. [MenuItem("My Commands/Add root motion curve")]
    2. public static void AddMotionCurve()
    3. {
    4.     var clips = Selection.GetFiltered(typeof(AnimationClip), SelectionMode.Assets)
    5.         .Cast<AnimationClip>();
    6.  
    7.     foreach (AnimationClip clip in clips)
    8.     {
    9.         var bindings = AnimationUtility.GetCurveBindings(clip);
    10.  
    11.         foreach (EditorCurveBinding sourceBinding in bindings)
    12.         {
    13.             if (sourceBinding.path != "")
    14.             {
    15.                 // We are only looking at the root component
    16.                 continue;
    17.             }
    18.  
    19.             var property = sourceBinding.propertyName;
    20.  
    21.             if (property.StartsWith("m_LocalPosition."))
    22.             {
    23.                 property = property.Replace("m_LocalPosition.", "MotionT.");
    24.             }
    25.             else
    26.             {
    27.                 // Not interested in this property
    28.                 continue;
    29.             }
    30.  
    31.             var binding = new EditorCurveBinding();
    32.             binding.path = "";
    33.             binding.type = typeof(Animator);
    34.             binding.propertyName = property;
    35.  
    36.             var curve = AnimationUtility.GetEditorCurve(clip, sourceBinding);
    37.  
    38.             AnimationUtility.SetEditorCurve(clip, binding, curve);
    39.         }
    40.     }
    41. }

    Test project (a scene with a cube and some animations) is attached.

    When I posted my previous message, I thought that MotionT is some hidden Unity parameter for root motion, however, it occurs to me, that it could be some property of TMPxyz's model. If that is the case, how can I use root motion without rig and model (just some GameObject hierarchy and Mechanim animations)?
     

    Attached Files:

  11. Mecanim-Dev

    Mecanim-Dev

    Joined:
    Nov 26, 2012
    Posts:
    1,675
    Not sure I understand your question sorry. But MotionT is an Animation curve generated by the model importer when you import an animation or can be created manually by a user script like you did. Since root motion drive always the root transform, it will work even with sprite because you need at least one game object in your scene to display sprite.
     
  12. nigredo_tori

    nigredo_tori

    Joined:
    Jul 11, 2014
    Posts:
    3
    I want to create an animation clip which will move my object (cube, for example) for some distance relative to its previous position. So if I loop this animation, the object would continue moving further and further away from the starting point, instead of just teleporting back on clip restart.

    Here's what I do:
    1. Create a new Unity Project
    2. Add a cube to the scene, select its GameObject in Hierarchy tree.
    3. Create an animation for the cube (Window -> Animation, Create New Clip) which changes cube's Position linearly from (0, 0, 0) to (5, 0, 0) over one second. Animator Controller is automatically created.
    4. Right now, if I press Play button, the cube travels 5 units along X axis, resets to zero, and starts over again.
    5. I add the script with previously mentioned command, save the project, select the animation asset, and launch the command. The script creates curves for properties "MotionT.x" "MotionT.y" "MotionT.z" with an empty path ("") and Animator type, taking the actual curve data from corresponding "m_LocalPosition" components
    6. If I press Play, the cube still travels 5 units and then starts over from zero.
    7. Now I delete clip's Position curves, leaving only MotionT curves ("Cube : Motion T" in animation window).
    8. You can see that the curve's value is not displayed correctly in an edit field:
    animation.PNG
    9. If I press Play, the cube doesn't move at all.

    Here are the clip's properties:
    properties.PNG

    Here's the relevant part of .anim file:
    Code (csharp):
    1.  
    2. m_FloatCurves:
    3.   - curve:
    4.       serializedVersion: 2
    5.       m_Curve:
    6.       - time: 0
    7.         value: 0
    8.         inSlope: 5
    9.         outSlope: 5
    10.         tangentMode: 10
    11.       - time: 1
    12.         value: 5
    13.         inSlope: 5
    14.         outSlope: 5
    15.         tangentMode: 10
    16.       m_PreInfinity: 2
    17.       m_PostInfinity: 2
    18.     attribute: MotionT.x
    19.     path:
    20.     classID: 95
    21.     script: {fileID: 0}
    22.   - curve:
    23.       serializedVersion: 2
    24.       m_Curve:
    25.       - time: 0
    26.         value: 0
    27.         inSlope: 0
    28.         outSlope: 0
    29.         tangentMode: 10
    30.       - time: 1
    31.         value: 0
    32.         inSlope: 0
    33.         outSlope: 0
    34.         tangentMode: 10
    35.       m_PreInfinity: 2
    36.       m_PostInfinity: 2
    37.     attribute: MotionT.y
    38.     path:
    39.     classID: 95
    40.     script: {fileID: 0}
    41.   - curve:
    42.       serializedVersion: 2
    43.       m_Curve:
    44.       - time: 0
    45.         value: 0
    46.         inSlope: 0
    47.         outSlope: 0
    48.         tangentMode: 10
    49.       - time: 1
    50.         value: 0
    51.         inSlope: 0
    52.         outSlope: 0
    53.         tangentMode: 10
    54.       m_PreInfinity: 2
    55.       m_PostInfinity: 2
    56.     attribute: MotionT.z
    57.     path:
    58.     classID: 95
    59.     script: {fileID: 0}
     
    Last edited: Sep 25, 2014
  13. Ramesh

    Ramesh

    Joined:
    May 19, 2013
    Posts:
    1
    @nigredo_tori
    1. Create the animation clip as you created for the cube
    2. Select the cube in project window
    3. In inspector click on 'Generate root motion curves '
    4. Now click on your cube in Hierarchy view, and tick apply root motion checbox on Animator Component
    5. An u are done.

    Enjoy :)
     
  14. username132323232

    username132323232

    Joined:
    Dec 9, 2014
    Posts:
    477
    What if the 'Generate root motion curves ' button is not there?

    no-root-motion.PNG
     
  15. ch_01

    ch_01

    Joined:
    Nov 17, 2009
    Posts:
    16
    I meet this question too,the 'Generate root motion curves ' button is not there,please reslove this question
     
  16. Mecanim-Dev

    Mecanim-Dev

    Joined:
    Nov 26, 2012
    Posts:
    1,675
    To been able to create a root motion curves you need first some animation curve on your root object and your object need to be setup as a generic rig(Humanoid rig handle the root motion automatically).
    The 'Generate root motion curves' button will only appear if both condition are true.
     
  17. ch_01

    ch_01

    Joined:
    Nov 17, 2009
    Posts:
    16
    I had some animation files,use generic rig,it correct in play mode,but in editor ,it can not to be edit,display missing ,I try to editor ,but will destory all key in the animation,how to do?

    the unitypackage is here!please help me ,thank !
     

    Attached Files:

  18. Arycama

    Arycama

    Joined:
    May 25, 2014
    Posts:
    184
    Does this still work with current versions of Unity? (I.e. 5.6) Assigning curves to MotionT.x/y/z or MotionQ.x/y/z/w only show yellow "Missing" text.
     
  19. Mecanim-Dev

    Mecanim-Dev

    Joined:
    Nov 26, 2012
    Posts:
    1,675
    @Arycama Yes it should still work.

    Can you share the code to show how you assign them?
     
  20. Arycama

    Arycama

    Joined:
    May 25, 2014
    Posts:
    184
    Whoops, didn't see this alert until now. Here's the code I'm using, it's a bit strange because I'm reading a long animation clip at runtime which I'm then splitting into several individual clips. One of the objects animated is called "Root Bone" so I'm assigning the Root Bone properties to the root transform. I check if they are localPosition or rotation, and assign them to "MotionT" and "MotionQ" respectively.

    Code (CSharp):
    1.  
    2. var curve = new AnimationCurve(newKeyframes.ToArray());
    3.  
    4. if (relativePath == "Root Bone")
    5. {
    6.     var end = propertyName.IndexOf('.');
    7.     var property = propertyName.Substring(0, end);
    8.     var data = propertyName.Substring(end);
    9.     switch (property)
    10.     {
    11.         case "localPosition":
    12.             propertyName = "MotionT" + data;
    13.             break;
    14.         case "localRotation":
    15.             propertyName = "MotionQ" + data;
    16.             break;
    17.         case "localScale":
    18.             continue;
    19.     }
    20.  
    21.     clip.SetCurve(string.Empty, typeof(Animator), propertyName, curve);
    22. }
    23. else
    24. {
    25.     clip.SetCurve(relativePath, typeof(Transform), propertyName, curve);
    26. }
    27.  
    This is the result in the animation window:

    Screenshot.png
     
  21. tinyant

    tinyant

    Joined:
    Aug 28, 2015
    Posts:
    127
    Hi, I have some confused things about Mecanim system.

    I have one Mocap Animation, everything is correct when I use Animator Control to play this Animaiton Clip with Humanoid setting.

    But when i covert Humanoid setting to legacy settings. the character have some offset not in the origin position when playing the LegacyAnimation Clip. (I want use Legacy System for playing Mocap Data anmation)

    Thanks for replaying.
    @Mecanim.Dev[/QUOTE]
     

    Attached Files:

  22. tinyant

    tinyant

    Joined:
    Aug 28, 2015
    Posts:
    127
    @Mecanim.Dev
    When hit play the character's origin position changed.
    But When I use Humanoid Animator Controller play the Mocap clip Everything was right.
    Thanks for replaying
     

    Attached Files:

  23. Mecanim-Dev

    Mecanim-Dev

    Joined:
    Nov 26, 2012
    Posts:
    1,675
    tinyant likes this.