public static class QuaternionExtensions
/// Smoothly damps between two rotations.
/// <param name="current">The current rotation.</param>
/// <param name="target">The target rotation.</param>
/// <param name="angularVelocity">The current angular velocity (in radians per second). This is modified by the function.</param>
/// <param name="smoothTime">Approximately the time it will take to reach the target. Smaller values will reach the target faster.</param>
/// <param name="maxAngularSpeed">Optionally, the maximum angular speed (in radians per second). Use Mathf.Infinity if no limit is desired.</param>
/// <param name="deltaTime">The time step to use (for example, Time.deltaTime).</param>
/// <returns>The new rotation after smoothing.</returns>
public static Quaternion SmoothDamp(Quaternion current, Quaternion target, ref Vector3 angularVelocity, float smoothTime, float maxAngularSpeed, float deltaTime)
// If no time passed, just return the current rotation.
if (deltaTime < Mathf.Epsilon)
// Compute the relative rotation from current to target.
// Note: The multiplication order matters.
Quaternion deltaRotation = target * Quaternion.Inverse(current);
// To ensure the shortest path is taken, we may need to negate the rotation.
if (deltaRotation.w < 0f)
deltaRotation.x = -deltaRotation.x;
deltaRotation.y = -deltaRotation.y;
deltaRotation.z = -deltaRotation.z;
deltaRotation.w = -deltaRotation.w;
// Convert the relative rotation to angle-axis form.
deltaRotation.ToAngleAxis(out float angleInDegrees, out Vector3 rotationAxis);
// When the angle is very small, ToAngleAxis might return NaN for the axis.
if (float.IsNaN(rotationAxis.x))
rotationAxis = Vector3.zero;
// Clamp the angle between -180 and 180 degrees.
if (angleInDegrees > 180f)
// Convert angle to radians for our damping calculations.
float angleInRadians = angleInDegrees * Mathf.Deg2Rad;
// The angular difference (as a vector) is the rotation axis multiplied by the angle (in radians).
Vector3 deltaAngle = (rotationAxis.normalized * angleInRadians);
// Smoothly damp the deltaAngle from 0 towards our desired delta.
// We use Vector3.SmoothDamp here. The “current” value is zero because we are measuring the delta.
Vector3 smoothedDeltaAngle = Vector3.SmoothDamp(Vector3.zero, deltaAngle, ref angularVelocity, smoothTime, maxAngularSpeed, deltaTime);
// Convert the smoothed angular difference back into a quaternion.
// (Remember that Quaternion.AngleAxis expects degrees.)
Quaternion smoothedRotation = Quaternion.AngleAxis(smoothedDeltaAngle.magnitude * Mathf.Rad2Deg,
smoothedDeltaAngle.sqrMagnitude < 1e-6f ? Vector3.up : smoothedDeltaAngle.normalized);
// Apply the smoothed rotation onto the current rotation.
return smoothedRotation * current;