New to this so please bear with me if there’s an obvious answer to this. I’ve set up a script that rotates the camera 90 degrees left/right on a button press and it works except that there’s a build of %error everytime I press a key. Eventually it ends up rotating in multiples of ~30 degrees. I understand that this is down to converting from Euler to Quaternion to Euler, but what I’ve not managed to find on the forums is how do I write the whole script using Quaternions?
IEnumerator RotateMe(Vector3 ang, float time)
{
var sAngle = transform.rotation;
var eAngle = Quaternion.Euler(transform.eulerAngles + ang);
for (var t = 0f; t < 1; t += Time.deltaTime / time)
{
transform.rotation = Quaternion.Lerp(sAngle, eAngle, t);
yield return null;
}
}
// Update is called once per frame
void Update () {
if (Input.GetKeyDown("left"))
{
StartCoroutine(RotateMe(Vector3.up * 90, 0.5f));
}
if (Input.GetKeyDown("right"))
{
StartCoroutine(RotateMe(Vector3.up * -90, 0.5f));
}
}
Quaternions are a tough mathematical topic so I recommend to get rid of Quaternions and Eulers conversions and use built in methods:
Coroutine coroutine = null;
bool canRunCoroutine = true;
IEnumerator RotateMe(Vector3 angle, float time)
{
float timer = 0f;
Quaternion rotation = transform.rotation;
canRunCoroutine = false;
while(timer < time)
{
transform.Rotate(angle * Time.deltaTime / time, Space.Self); //can also be Space.World to rotate it in world space instead of local space
timer += Time.deltaTime;
yield return new WaitForEndOfFrame();
}
transform.rotation = rotation;
transform.Rotate(angle, Space.Self); //set rotation by hand, exactly like it's supposed to be
canRunCoroutine = true;
}
void Update()
{
if(Input.GetKeyDown("left") && canRunCoroutine) //canRunCouroutine to make sure you will not get other angles than 0, 90, 180 and 270.
{
StartCoroutine(RotateMe(Vector3.up * 90, 0.5f));
}
if(Input.GetKeyDown("right") && canRunCoroutine)
{
StartCoroutine(RotateMe(Vector3.up * -90, 0.5f));
}
}
Perhaps use GetKey instead of GetKeyDown for smooth rotations while holding down the key.
As I understand, it ends up rotating by 30°, but at the begining, the rotation is almost correct no? If I understand correctly:
My solution would be to store your Y rotation as an Integer variable (ie: yRot). Each time you rotate from key press you could add +/-90 to that int. When you reach 360, yRot = 0. if you reach -90, yRot = 270
and you could then do (not tested, am at work):
IEnumerator RotateMe(float time)
{
var sAngle = transform.rotation;
var eAngle = tranform.rotation;
eAngle.y = yRot;
for (var t = 0f; t < 1; t += Time.deltaTime / time)
{
transform.rotation = Quaternion.Lerp(sAngle, eAngle, t);
yield return null;
}
}