Is there a way to extract rootmotion curves from a clip

I would like to use hip curve’s root motion data
(for playing it regularly and/or at a normalized time of the clip)

and on a humanoid that has root motion switch off (something like a requirement)
probably could get the hip data when playing the anim clip, not sure

probably this function did that, which is now obsolete

this says on any animated properties (but is there a way to get that data?)

this sound good, but questionable now if will be able to use it
Thus array of keyframes is returned instead of a singular curve object.

public static ObjectReferenceKeyframe[] GetObjectReferenceCurve(AnimationClip clip, EditorCurveBinding binding);

there has been some discussions about this, but didn’t find an answer to
to don’t want to remove or add curve
here’s how to add rootmotion

but MecanimAnimator says

so MotionT and MotionQ is there somewhere, isn’t it

I’m not sure if this example.cs is still working or if would get hip’s rootmotion

1 Like

_clip is the clip you’re looking at and rootMotionNodeName would be your hip/root motion joint’s path:

var curveBindings = UnityEditor.AnimationUtility.GetCurveBindings(_clip);
foreach (var curveBinding in curveBindings)
{
  if (curveBinding.path == rootMotionNodeName)
  {
    //Debug.Log(curveBinding.path + ", " + curveBinding.propertyName);
    var editorCurve = UnityEditor.AnimationUtility.GetEditorCurve(_clip, curveBinding);
  }
}

hey, thanks.
maybe this could lead to something.

one thing. the clip cannot be humanoid, it must be generic.
if humanoid, curveBinding.path returns empty.

for the record, this Debug.Log(curveBinding.path + ", " + curveBinding.propertyName);
looks like this for RunForward_NtrlFaceFwd.fbx
4087312--356779--clipbindingsx0.jpg
4087312--356785--clipbindingsx.jpg

now would need this var editorCurve turn into AnimationCurve what it is, but that is not so simple either

ah, yeah, if just AnimationUtility.GetEditorCurve without UnityEditor I’m getting some curve

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;

public class getACurves : MonoBehaviour {

    public AnimationClip _clip;
    public string boneName;

    public AnimationCurve curve;

    void Start () {

        var curveBindings = UnityEditor.AnimationUtility.GetCurveBindings(_clip);


        foreach (var curveBinding in curveBindings)
        {

            //Debug.Log(curveBinding.path + ", " + curveBinding.propertyName);

            if (curveBinding.path == boneName)
            {
                curve = AnimationUtility.GetEditorCurve(_clip, curveBinding);
                Debug.Log("curve> " + curveBinding.path + ", " + curveBinding.propertyName);
            }
        }

    }

}

would need to filter them by propertyName yet

1 Like

Ahh, it hadn’t occurred to me that root motion might work differently for humanoid rig clips as I don’t use any of the built in mecanim retargeting.

So given the root motion node’s animation curves from above, to get total root motion for a clip at time t, I do something along the lines of:
for curve localPosition.x, localPosition.y, etc.
p0 = evaluate curve at time 0 (AnimationCurve::Evaluate)
p1 = evaluate curve at time t
motion = p1 - p0

Same deal with rotation, etc. I also strip out a bunch of unneeded curves including root motion on import, storing stripped animation clip, root motion curves and other metadata in another asset which I use internally with custom Playables mixer. Requires more scaffolding around your animation setup but also allows complete control over how root motion is treated.

yeah, it can be usable for many thing: anim rootmotion modif, between-states, poses, animating etc
I guess unity’s Kinematica does this too, first it extracts all curves from the clips

humanoid/generic is not a problem with mixamo 'cause the gen version got the same animation and same root curves

the hip/root curves

and if I use these curves to move a transform

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class moveByCurves : MonoBehaviour {
    public getACurves getACurves;
    public Transform mover;
    public float time;
    //for root there's 10 curves: rotation[4], position[3], scale[3]
    //all other bones 7: rotation[4], scale[3]
    public int curvN = 10;
    int i;
    public bool isRoot;
    void Update () {
        time = Time.time;
        if (isRoot) {
            mover.rotation = new Quaternion (
                getACurves.curve [0].Evaluate (time), 
                getACurves.curve [1].Evaluate (time), 
                getACurves.curve [2].Evaluate (time), 
                getACurves.curve [3].Evaluate (time)
            );
            mover.position = new Vector3 (
                getACurves.curve [4].Evaluate (time), 
                getACurves.curve [5].Evaluate (time), 
                getACurves.curve [6].Evaluate (time)
            );
        }
        if (!isRoot) {
            mover.localRotation = new Quaternion (
                getACurves.curve [0].Evaluate (time), 
                getACurves.curve [1].Evaluate (time), 
                getACurves.curve [2].Evaluate (time), 
                getACurves.curve [3].Evaluate (time)
            );
        }
    }
}

then it looks alright
4090180--357112--roothip.gif

but doesn’t match up with legs

which might be a localRotation (*not rotation) issue
will test later
4090180--357118--bodycrv.gif

2 Likes

okay, had to check it now

it is localRotation
4090204--357121--bodycrv2.gif

updated the script above

3 Likes

used these scripts to get and modify root motion curves
frog had only one jump, and wanted to have blendtree of short and long jump

6135083--669125--frogrootmotion.gif
the original animation has been rotated (not lookin the direction of the “T-pose”)
so had used just the root curves (and added rotation)
and other bones has been played by animator (sync.state)

6135083--669131--playBonesCurves.jpg

6135083–669134–getBonesPath.cs (4.46 KB)
6135083–669137–playBonesCurves.cs (2.57 KB)

2 Likes

sorry if I write under this old post. I have a list of AnimationCurve. Can I merge them to export to fbx to use this new animation?

there’s no script/package that would do that to my knowledge.

you can record the animation being played in unity (like w playBonesCurves.cs)
there’s couple possibilities for that:

  • Scene Motion Capture (.anim)
  • Final IK’s baker (.anim)
  • Skele’s DAE exporter (.anim > .dae)
  • UnityTech’s fbx exporter

Thanks guys for digging into this, will be much helpfull in our case !
I’m binding this into the validate step so I can extract the curves to use while in play mode.