/// <summary> /// Shakes the vector several times in a random value, up to amount in magnitude. /// </summary> /// <param name="amount">The maximum displacement of the rotation, in degrees.</param> /// <param name="numShakes"> The number of shakes to perform. </param> public static CommandDelegate Shake(Ref <Quaternion> rotation, float amount, int numShakes, double duration) { CheckArgumentNonNull(rotation); if (amount <= 0f || amount > 180f) { throw new ArgumentOutOfRangeException("amount", "Must be larger than 0."); } if (numShakes <= 0) { throw new ArgumentOutOfRangeException("numBounces", "Must be larger than 0."); } amount = Mathf.Abs(amount); double avgDuration = duration / (numShakes + 1); CommandDelegate[] list = new CommandDelegate[numShakes + 1]; return(Cmd.Defer( () => { var baseVal = rotation.Value; for (int i = 0; i < numShakes; ++i) { // Generate an offset within the range -amount, amount var offset = Quaternion.Euler( UnityEngine.Random.Range(-amount, amount), UnityEngine.Random.Range(-amount, amount), UnityEngine.Random.Range(-amount, amount) ); float angle = Quaternion.Angle(Quaternion.identity, offset); // Clamp the offset if (angle > amount) { float t = UnityEngine.Random.Range(0f, angle / amount); offset = Quaternion.LerpUnclamped(Quaternion.identity, offset, t); } list[i] = Cmd.RotateTo(rotation, baseVal * offset, avgDuration); } list[numShakes] = Cmd.RotateTo(rotation, baseVal, avgDuration); return Cmd.Sequence(list); } )); }
public static void TestRotateTo() { Quaternion quatStart = Quaternion.Euler(10.0f, 20.0f, 30.0f); Quaternion quatEnd = Quaternion.Euler(30.0f, 20.0f, 10.0f); Quaternion quatVal = quatStart; Ref <Quaternion> quatRef = new Ref <Quaternion>( () => quatVal, t => quatVal = t ); CommandQueue queue = new CommandQueue(); queue.Enqueue( Cmd.Repeat(2, Cmd.RotateTo(quatRef, quatEnd, 1.0) ) ); queue.Update(0.5); AreEqual(quatVal, Quaternion.Slerp(quatStart, quatEnd, 0.5f), 0.000001f); quatVal = Quaternion.identity; queue.Update(0.5); AreEqual(quatVal, quatEnd, 0.000001f); queue.Update(0.5); AreEqual(quatVal, quatEnd, 0.000001f); // Make sure the rotation ends in the correct position when given a complex easing function. queue = new CommandQueue(); quatVal = quatStart; queue.Enqueue( Cmd.RotateTo(quatRef, quatEnd, 1f, Ease.OutElastic()) ); while (!queue.Update(1 / 30f)) { } AreEqual(quatVal, quatEnd, 0.001f); }