Search Unity

  1. Unity 2019.1 is now released.
    Dismiss Notice

Reading keyframe/curve data from Animator at runtime

Discussion in 'Animation' started by DerekMcKinley, May 3, 2019.

  1. DerekMcKinley

    DerekMcKinley

    Joined:
    Jun 24, 2014
    Posts:
    10
    Hi community

    I know that this has been answered on other occasions and always the answer is no, but I would like to know if in the current versions of unity this is no longer a problem.

    I want to be able to read runtime the keyframes/curves of the current animation, specifically of a bone, for example the pelvis of the character, the final goal is to draw the route of the chosen bone corresponding to the animation that is being executed.

    Maybe there are restrictions for the type of animation, it can be a legacy/humanoid or any other, I just want to know if it is possible.

    Thank you for reading
     
  2. dibdab

    dibdab

    Joined:
    Jul 5, 2011
    Posts:
    769
    it is possible for generic animations.

    you'll need the whole path for the bones, like
    bones [4] = bones [3] + "/" + prefix + "Neck";
    bones [5] = bones [4] + "/" + prefix + "Head";

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEditor;
    5.  
    6. public class getCRCurves : MonoBehaviour {
    7.  
    8.     //gets animation curves for a bone from a clip
    9.     //for generic animations
    10.     public AnimationClip _clip;
    11.     public bool getCurves = true;
    12.  
    13.     //check if the bone name in the clip equals
    14.     public string bone = "Hips";
    15.     [Header("Curves")]
    16.     [SerializeField] public AnimationCurve[] hip;
    17.     int i;
    18.     public bool doDebug = true;
    19.  
    20.     void Start () {
    21.  
    22.         if (getCurves) {
    23.  
    24.             hip = new AnimationCurve[7];
    25.             var curveBindings = UnityEditor.AnimationUtility.GetCurveBindings (_clip);
    26.  
    27.                 foreach (var curveBinding in curveBindings) {
    28.                     if (doDebug) Debug.Log (curveBinding.path + ", " + curveBinding.propertyName);
    29.  
    30.                     if (curveBinding.path == bone && !curveBinding.propertyName.Contains ("LocalScale")) {
    31.                         hip [i] = AnimationUtility.GetEditorCurve (_clip, curveBinding);
    32.                         if (doDebug) Debug.Log ("curve> " + i + " " + curveBinding.path + ", " + curveBinding.propertyName);
    33.                         i++;
    34.                     }
    35.                 }
    36.             getCurves = false;
    37.         }
    38.     }
    39. }
    40.  
    you might be able to do this for humanoid with

    animator.Play (animstate, -1, normalizedanimtime);

    like getting the localR of bones if they rotated a certain angle (or a certain amount of time has passed)
     
    Last edited: May 3, 2019
    DerekMcKinley likes this.
  3. DerekMcKinley

    DerekMcKinley

    Joined:
    Jun 24, 2014
    Posts:
    10
    GIF3.gif

    @dibdab thank you very much for answering
    Now I can to draw the trajectory of the bone specified in this case "Hips", but I have noticed several problems.

    1. The trajectory that I draw is built by the list of 3d vectors of the base bone, is an incorrect way to graph the curves but it works, if someone knows how to graph animationCurves in 3d space please show me how I can do it, I made a search and I found nothing, should be using the mathematical formulas but I think this is not available.

    2. Animation curves only have the local rotation for the other parts of the body (hands, feet), that means that I can not choose their position in the time of the animation.

    I followed the path of breadcrumbs and found a post where you show how you animate a model superimposed on another using the curves, but I do not understand yet how you achieve this if the curves only offer local position, how do you make to match the positions?
    To match the trajectory of the curve and my character I had to move everything to the 0,0,0 position:D
     
  4. dibdab

    dibdab

    Joined:
    Jul 5, 2011
    Posts:
    769
    you can have references of hands/feet and get their position runtime
    or calculate their position from the hip position, with the localrotations (probably)

    in that post the blue one is humanoid, the yellow one is generic (animated by curves)
     
    DerekMcKinley likes this.
  5. dibdab

    dibdab

    Joined:
    Jul 5, 2011
    Posts:
    769
    found a way to extract curves from a humanoid animation
    [from this editor tool: AnimationCurveTools]
    with the getAllCurves method, which is obsolete, but works in 5.6

    the animation curves are in different order than the muscles and the root rotation is off yet*
    getallcurves.gif



    *okay, you just need to put the rootmotion curve values after SetHumanPose

    Code (CSharp):
    1. humanPoseHandler.SetHumanPose (ref humanPose);
    2. root.position = new Vector3(getAllCurves.sourceCurves[rootP[0]].Evaluate(timeNow), getAllCurves.sourceCurves[rootP[1]].Evaluate(timeNow), getAllCurves.sourceCurves[rootP[2]].Evaluate(timeNow));
    3. root.rotation = new Quaternion(getAllCurves.sourceCurves[rootR[0]].Evaluate(timeNow), getAllCurves.sourceCurves[rootR[1]].Evaluate(timeNow),getAllCurves.sourceCurves[rootR[2]].Evaluate(timeNow),getAllCurves.sourceCurves[rootR[3]].Evaluate (timeNow));
     

    Attached Files:

    Last edited: May 20, 2019
    DerekMcKinley likes this.
  6. DerekMcKinley

    DerekMcKinley

    Joined:
    Jun 24, 2014
    Posts:
    10
    Great, I'm going to do some tests with this

    Thanks