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.