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
  3. Dismiss Notice

Question Augment animation and replace the original during runtime

Discussion in 'Scripting' started by amarthgul, May 24, 2024.

  1. amarthgul

    amarthgul

    Joined:
    Jun 12, 2019
    Posts:
    1
    I have some animation files that I wish to augment, make them more exaggerated. Like making the wrist rotate 60 degrees instead of the 30 on the original animation.

    This is achieved by a scale method:

    Code (CSharp):
    1. private AnimationCurve ScaleCurve(AnimationCurve inputCurve, float maxX, float maxY)
    2. {
    3.     AnimationCurve scaledCurve = new AnimationCurve();
    4.  
    5.     for (int i = 0; i < inputCurve.keys.Length; i++)
    6.     {
    7.         Keyframe keyframe = inputCurve.keys[i];
    8.         keyframe.value = inputCurve.keys[i].value * maxY;
    9.         keyframe.time = inputCurve.keys[i].time * maxX;
    10.         keyframe.inTangent = inputCurve.keys[i].inTangent * maxY / maxX;
    11.         keyframe.outTangent = inputCurve.keys[i].outTangent * maxY / maxX;
    12.  
    13.         scaledCurve.AddKey(keyframe);
    14.     }
    15.  
    16.     return scaledCurve;
    17. }
    With this, I can then retrieve the animation curve, apply the scaling, and then apply them back:

    Code (CSharp):
    1. Animator mainAnimator;
    2. int layer;
    3.  
    4. // Inside of the Start() method:
    5. EditorCurveBinding[] bindings =
    6.     AnimationUtility.GetCurveBindings(
    7.         mainAnimator.runtimeAnimatorController.animationClips[layer]
    8.         );
    9.  
    10. for (int i = 0; /* Selecting the desired index */ )
    11. {
    12.     AnimationCurve currentCurve = AnimationUtility.GetEditorCurve(
    13.         mainAnimator.runtimeAnimatorController.animationClips[layer],
    14.         bindings[i]
    15.         );
    16.  
    17.     // Scale here, time scale remains the same but twice the amplitude
    18.     currentCurve = ScaleCurve(currentCurve, 1, 2.0f);
    19.  
    20.     AnimationUtility.SetEditorCurve(
    21.         mainAnimator.runtimeAnimatorController.animationClips[layer],
    22.         bindings[i],
    23.         currentCurve);
    24. }
    This did work, but I realized the changes seem to be permanent. If I ran the game twice, then the animation would be scaled 4 times, by the 3rd time I ran it the animation is 8 times (2^3) as strong...

    I thought about storing the original and revoke back to the original when it's done, but it turned out to be really hard to decide when it is "done", especially during testing.

    What would be a way to make this amplification/exaggeration lasting only during the runtime?