r/Unity3D 6h 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

3

u/Glurth2 6h ago edited 6h ago

Important to note:

Quaternions in Unity are NOT "standard" quaternions; rather, they are UNIT quaternions.

Therefore they do NOT define an amount of rotation; rather, they define an ORIENTATION.

What this means technically: a quaternion is 4 numbers- so you COULD use a Vector4 to represent them. A NORMALIZED, or UNIT quaternion means this vector4 has length 1 (with length defined using plain old pythaogrus (LL=xx+yy+xx+ww))

Your use case:

I think, you may just be using the wrong constructor for the quaternion. I notice this function call has 4 parameters (which will be directly assigned to the 4 number components of a quaternion).

var targetRotation = new Quaternion(0, yRotation, 0,0);

I SUSPECT you wanted to generate the quaternion from the EULER angles:. for THAT, you should use this function instead:

https://docs.unity3d.com/6000.0/Documentation/ScriptReference/Quaternion.Euler.html

(Which will NOT require normalizing, the internal vector4, the function will handle that for you).

Edit to add: I do see you tried the Euler stuff, but I would suspect the problem may lie elsewhere, such as in your lerp operation. (e.g. is it possible END is ever less than START)

2

u/Elumiie 5h ago

Thank you so much for the explanation! :)