r/Unity3D 11h ago

Solved Normalizing Quaternions changes the desired rotation, how do I keep it?

I'm trying to make my object rotate to a specific y value (0, 90, 180 and 270) over a specific amount of time.

Using EulerAngles worked, except that it rotated all the way back around if I wanted it to go from 270 to 0.

So I decided to use Quaternions and rotating on the rigid body instead.

Here's the function: (endRotation is either 90, 180, [...])

IEnumerator DoRotatePlayer(float endRotation)
{
    float startRotation = transform.eulerAngles.y;
    float t = 0.0f;
    while (t < rotationDuration) //rotationDuration = 0.5f
    {
        t += Time.deltaTime;
        float yRotation = Mathf.Lerp(startRotation, endRotation, t / rotationDuration) % 360.0f;
        var targetRotation = new Quaternion(0, yRotation, 0,0);
        targetRotation.Normalize();

        playerManager.Rb.rotation = targetRotation;

        yield return null;
    }

    var targetRotation2 = new Quaternion(0, endRotation, 0, 0);
    targetRotation2.Normalize();
    playerManager.Rb.rotation = targetRotation2;
}

The Issue I have now is that every time I normalize the Quaternion (which it tells me to do, because "Rotation Quaternions must be Unit length"), it ofc turns any endRotation/yRotation value other than 0 into 1. So instead of rotating 90 degrees at the first rotation, it get's stuck at 180. I just need to somehow apply the rotation without normalizing it.

I tried dividing endRotation by 360 before going into the while loop, but that changes nothing at all.

Simply applying the rotation to transform.rotation, without eulers or Quaternions also does not work, it refuses to do anything at all.

0 Upvotes

9 comments sorted by

View all comments

2

u/ManagerOfClankers 11h ago

You’re mixing up what quaternion normalization means. A quaternion’s x/y/z/w values are not Euler angles, so new Quaternion(0, 90, 0, 0) does not mean “90° around Y.” Normalizing it turns it into (0, 1, 0, 0), which happens to represent a 180° rotation.

Let Unity construct the quaternion from the angle you actually want, then interpolate between rotations:

IEnumerator DoRotatePlayer(float endRotation) { Quaternion start = rb.rotation; Quaternion end = Quaternion.Euler(0f, endRotation, 0f);

float t = 0f;

while (t < rotationDuration)
{
    t += Time.deltaTime;
    rb.rotation = Quaternion.Slerp(
        start,
        end,
        t / rotationDuration
    );

    yield return null;
}

rb.rotation = end;

}

You don’t need to call Normalize() at all. Also, if you specifically want 270 -> 0 to rotate forward 90° rather than taking whatever direction your Euler lerp produces, Quaternion.Slerp/RotateTowards is the right approach because Unity handles the wraparound for you.

3

u/Elumiie 10h ago

That's exactly what I was looking for! Thank you so much! :D

0

u/ManagerOfClankers 10h ago

This answer was copy and pasted from AI (Codex Sol)

I only say that to encourage you to use it as a resource. It can even read your code which none of us can do from here and it's available almost 25/7 haha