Search Unity

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:
    19
    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:
    976
    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
    Malbers, Genso_0 and DerekMcKinley like this.
  3. DerekMcKinley

    DerekMcKinley

    Joined:
    Jun 24, 2014
    Posts:
    19
    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:
    976
    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:
    976
    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:
    19
    Great, I'm going to do some tests with this

    Thanks
     
  7. Eristen

    Eristen

    Joined:
    Jun 17, 2021
    Posts:
    17
    Hi. I am not sure if this answers the question completely, but if all you need is the value of an animation curve then you can use this obscure fact

    "If you have a curve with the same name as one of the parameters in the Animator Controller, then that parameter takes its value from the value of the curve at each point in the timeline. For example, if you make a call to GetFloat from a script, the returned value is equal to the value of the curve at the time the call is made"

    See the link bellow

    https://docs.unity3d.com/Manual/AnimationCurvesOnImportedClips.html
     
    Yuchen_Chang, Aoedipus and hareok2000 like this.
  8. Gekigengar

    Gekigengar

    Joined:
    Jan 20, 2013
    Posts:
    738
    I am trying to create a custom animator, and need to know the object and the property value change of the object binded to it at runtime. But everything is only available through AnimationUtility class. I am thinking to bake the data in editor into my own Animation Clip for use in runtime, but that’s double the data! Ideally I can use Unity’s and access it from their’s!
     
  9. OmarVector

    OmarVector

    Joined:
    Apr 18, 2018
    Posts:
    130
    i know its old thread, but this solution for editor, not at runtime

    AnimationUtility.GetCurveBindings() is from Editor namespace and will be stripped in the build
     
  10. JuanGuzmanH

    JuanGuzmanH

    Joined:
    Feb 8, 2018
    Posts:
    74
    I’m in the same situation. I need in my final build read some curves from the clip is currently playing at runtime. I’m trying to remap some blend shapes, so reading from current bones or blend shapes being animated is not a solution for me. I need the curve from the clip.
    Anyone with an idea?
     
  11. Yuchen_Chang

    Yuchen_Chang

    Joined:
    Apr 24, 2020
    Posts:
    126
    Dumb way, but if all clips are in your project (i.e. not in an asset-bundle from other projects), then you can create a container class to contain all the curves before you build it to a player.
     
    JuanGuzmanH likes this.