tmighty
tmighty

Reputation: 11399

eulerAngles from Vector3 results in strange rotation

I'm trying to change the eulerAngle X of a camera rotation while keeping y and z at 0.

However, the following IEnumerator results in strange eulerAngles like 10, -74.653, 0.

enter image description here

I don't understand how the y value can change within the following function:

private IEnumerator LerpCameraNormalRot()
{
    float duration = 0.5f;

    for (float t = 0f; t < duration; t += Time.deltaTime)
    {
        float f = Mathf.Lerp(camera.transform.eulerAngles.x, 10, t / duration);
        Vector3 vNew = new Vector3(f, 0, 0);
        camera.transform.eulerAngles = vNew;
        yield return 0;
    }
}

Isn't this strange? I never change the Y and Z values!

I only want to change the X rotation (eulerAngle.x) from its current value to 10.

Thank you for the help!

Upvotes: 3

Views: 1333

Answers (2)

derHugo
derHugo

Reputation: 90669

Unity uses two representation of rotation, position, eulerAngles, etc

  • one is in worldspace
  • the other is in local space

The values not including local in their name are in world space. If your object has than any parents that are rotated/scaled/translated you won't see the values you set in Unity since the Transform inspector displays the local coordinates.

If you want to set the local coordinates to the exact values instead use localPosition, localRotation or localEulerAngles instead.

For me it looks like you want to rotate the Camera around its local x axis by 10° in 0.5 secons.

So I think you could instead do it like

private IEnumerator LerpCameraNormalRot()
{
    float duration = 0.5f;

    float initialRotationX = camera.transform.localEulerAngles.x;
    float targetRotationX = 10;

    for (float t = 0f; t < duration; t += Time.deltaTime)
    {
        float currentX = Mathf.Lerp(initialRotationX, targetRotationX, t / duration);

        camera.transform.localEulerAngles = new Vector3(currentX , 0, 0);

        // Which would be the same as using 
        // camera.transform.localRotation = Quaternion.Euler(new Vector3(currentX, 0, 0));

        yield return null;
    }

    // to be sure you have no overshooting you could set the target rotation fix here as well
    camera.transform.localEulerAngles = new Vector3(targetRotation, 0 ,0);

    // or
    // camera.transform.localRotation = Quaternion.Euler(new Vector3(targetRotation, 0, 0));
} 

Upvotes: 2

Ruzihm
Ruzihm

Reputation: 20259

You are setting the eulerAngles but that will result in different localEulerAngles which are indicated by the red box in your image. If the object has any ancestors that are rotated, they will probably not match!

To fix your immediate problem, you could use localEulerAngles instead of eulerAngles:

float f = Mathf.Lerp(camera.transform.localEulerAngles.x, 10, t / duration);
Vector3 vNew = new Vector3(f, 0, 0);
camera.transform.localEulerAngles= vNew;

The problem with this is that it does not account for the ability to go from 359 degrees around to 0 degrees. Better yet would be to use Quaternion.Euler and Quaternion.Slerp to use Quaternions rather than Euler angles:

private IEnumerator LerpCameraNormalRot()
{
    float duration = 0.5f;
    Quaternion startRotation = camera.transform.localRotation;
    Quaternion goalRotation = Quaternion.Euler(10f, 0f, 0f);

    for (float t = 0f; t < duration; t += Time.deltaTime)
    {   
        camera.transform.localRotation = Quaternion.Slerp(startRotation, goalRotation, t/duration);
        yield return 0;
    }

    camera.transform.localRotation = goalRotation;
}

Upvotes: 2

Related Questions