- Home /
Rotating smoothly between two angles - Mathematical formula?
I'd like to have an object rotate smoothly between two angles, similar two a metronome or a rocking chair, but I can't seem to figure out the mathematical formula to do it.
I guess what I'm really asking is not necessarily a question of angles, but rather, how to smoothly shift back and forth between two numbers.
Answer by phxvyper · Jun 17, 2016 at 08:04 PM
In Vector math, what you're talking about is called Interpolation. You have a few options when it comes to smoothly Interpolating between two numbers.
You can use Mathf.Lerp to Linearly Interpolate between two floats:
public float TimeSinceRotationStart = 0f;
public float RotationTime = 1f; // Take 1 second to rotate fully
public float CurrentLerpValue = 0f;
public float Start = 0f;
public float Finish = 100f;
void Update() {
float percentageDone = TimeSinceRotationStart / RotationTime; // The percentage value, represented as a number between 0 and 1
CurrentLerpValue = Mathf.Lerp(Start, Finish, percentageDone);
}
You can use Vector3.Lerp to Linearly Interpolate between two Euler Angles:
public float TimeSinceRotationStart = 0f;
public float RotationTime = 1f; // Take 1 second to rotate fully
public Vector3 CurrentLerpValue;
public Vector3 Start;
public Vector3 Finish = new Vector3(0f, 100f, 0f);
void Update() {
float percentageDone = TimeSinceRotationStart / RotationTime; // The percentage value, represented as a number between 0 and 1
CurrentLerpValue = Vector3.Lerp(Start, Finish, percentageDone);
}
You can use Quaternion.Slerp for Spherically Linearly Interpolated rotation. Slerp uses a Quaternion to create a smooth movement that smoothly accelerates then smoothly decelerates. You should give it a try and see if you like it, after trying out the other Lerp options of course.
public float TimeSinceRotationStart = 0f;
public float RotationTime = 1f; // Take 1 second to rotate fully
public Quaternion CurrentLerpValue;
public Quaternion Start = Quaternion.Euler(0f, 0f, 0f); // Convert 3D euler angles (x,y,z) to a 4D Quaternion (w,x,y,z)
public Quaternion Finish = Quaternion.Euler(0f, 100f, 0f);
void Update() {
float percentageDone = TimeSinceRotationStart / RotationTime; // The percentage value, represented as a number between 0 and 1
CurrentLerpValue = Vector3.Lerp(Start, Finish, percentageDone);
}
If you want to create a sort of Ping Pong type back and forth movement, implementing that with any of these functions is simple enough, but you can also use the PingPong (click here) method.
Answer by ericbegue · Jun 17, 2016 at 08:00 PM
Oscillations are often modelled using the sine function. For instance y = sin(x) will make y oscillates back and forth between 1 and -1 as x increases.
Answer by cdnDave · Jun 17, 2016 at 08:16 PM
A common way of smoothly going between two values is to use the Sin function. As the number passed into the Sin function increases the returned value will move between -1 and 1. With a little math you can turn that range into whatever you need. For example, with the following code the value of angle will smoothly go between 0 and 60.
float multiplier = 2f; //Change this value to control the frequency of the sin wave
float angle = 30f + Mathf.Sin(multiplier * Time.realtimeSinceStartup) * 30f;
Answer by JedBeryll · Jun 17, 2016 at 08:25 PM
For one there is Vector3.Lerp for smoothly changing direction (also Quaternion Lerp and Slerp). As for the back and forth thing... maybe a Mathf.Sin would do what you want? For example: increase a float by Time.deltaTime in Update and get the sinus of that value. Finally pass that value to the Lerp function as its last parameter.
float f = 0f;
void Update() {
f += Time.deltaTime;
float sin = (Mathf.Sin(f) + 1f) / 2;
//Sin returns a value between -1 and 1 but Lerp takes a value
//between 0 and 1 so I'm converting it to a value between 0 and 1
Vector3 dir = Vector3.Lerp(direction1, direction2, sin);
}
I never tested this but i think it would work. Not sure what exactly you want to do with this so maybe Vector3.Slerp is better for you. Difference is Slerp treats the vector as a direction and Lerp treats it as a position.
You can speed up or slow down the interpolation if you multiply deltaTime with another float. Hope this helps!