Home > Back-end >  Why is my animation jumping to the last keyframe when set in script?
Why is my animation jumping to the last keyframe when set in script?

Time:07-16

I am trying to rotate a gameObject by scripting it. This gameObject is a bone added in SkinningEditor, which should not make a difference. The script I wrote below is attached to the bone.

using System.Collections;
 using System.Collections.Generic;
 using UnityEngine;
 
 public class DeformBone : MonoBehaviour
 {
     void LateUpdate()
     {
         setAllCurves();
     }
 
 
     private void setAllCurves()
     {
         var angle = Quaternion.Euler(0, 0, 5);
 
         var rotXcurve = AnimationCurve.EaseInOut(0, 0, 5, angle.x);
         var rotYcurve = AnimationCurve.EaseInOut(0, 0, 5, angle.y);
         var rotZcurve = AnimationCurve.EaseInOut(0, 0, 5, angle.z);
         var rotWcurve = AnimationCurve.EaseInOut(0, 0, 5, angle.w);
 
         // set the curve here
         AnimationClip clip = new AnimationClip();
         clip.legacy = true;
 
         clip.SetCurve("", typeof(Transform), "localRotation.x", rotXcurve);
         clip.SetCurve("", typeof(Transform), "localRotation.y", rotYcurve);
         clip.SetCurve("", typeof(Transform), "localRotation.z", rotZcurve);
         clip.SetCurve("", typeof(Transform), "localRotation.w", rotWcurve);
 
         // play the curve here
         if (gameObject.GetComponent<Animation>() == null)
         {
             // add the component
             var animation = gameObject.AddComponent<Animation>();
             animation.playAutomatically = false;
             animation.wrapMode = WrapMode.PingPong;
             
         }
 
         GetComponent<Animation>().AddClip(clip, "rotateyo");
         GetComponent<Animation>().Play("rotateyo");
     }
 }

However, the animation jitters quickly back and forth, jumping from keyframe to keyframe and then it gets faster and faster until it just looks a bit crazy. I want it to rotate at the angle indicated slowly. I have tried putting this in Start() - this only jumps it to the last keyframe where it stays, and FixedUpdate/Update where the same thing happens.

I can see in the Inspector that I have successfully added an Animation to the bone and that the curves are being set up properly. What am I doing wrong?

CodePudding user response:

I guess your problem starts in the last line:

GetComponent<Animation>().Play("rotateyo");

This will play the animation, but the 2nd (optional) parameter defaults to PlayMode mode = PlayMode.StopSameLayer - I guess the continuous calling of "Play" (each LateUpdate) in combination with your "PingPong" Type probably gets your animation stuck on the last keyframe!


Also: I fear you cannot just lerp each of a quaternion's parameters... You should have a look at Quaternion.Lerp and use your eased curve as t.


if you just want to "rotate object through script" I'd not use the animation at all. Example:

yourBone.Rotate(0, 0, Time.deltaTime);

Example with ease:

Quaternion startRot = Quaternion.Identity; // "no rotation"
Quaternion endRot = Quaternion.Euler(0, 0, 90);
AnimationCurve curve = AnimationCurve.EaseInOut(0, 0, 1, 1);
float easedTime = curve.Evaluate(PingPong(Time.time, 2));
yourBone.rotation = Quaternion.Lerp(startRot, endRot, easedTime);

edit: if your easing overshoots, you may want to use Quaternion.LerpUnclamped so that it can overshoot the target rotation.

  • Related