Search code examples
unity-game-enginecamerarotationunityscript

Transform rotation (Slerp) - Unity


I'm trying to change the position and rotation of the main camera with the space bar. To change the position i have no problems, but finding problems to rotate the camera on the z axis. Initially the rotation is set to 359.9f, after pressing the space bar the rotation is set to 179.9f but when i go back to the original rotation (359.9f) the direction of rotation is different.

This is my code:

using UnityEngine;
using System.Collections;

public class Untitled : MonoBehaviour {

    //Lerp Position
    private Vector3 start;
    private Vector3 end;

    //Lerp Time
    private float lerpTime = 3f;
    private float currentLerpTime = 0;

    // Camera Up - Down
    public bool up = false;


    void Update () {

        start = Camera.main.transform.position;
        end = new Vector3 (Camera.main.transform.position.x, 105, Camera.main.transform.position.z);

        //Quaternions
        Quaternion RotationA = Quaternion.Euler (0, 0, 179.9f);
        Quaternion RotationB = Quaternion.Euler (0,0, 359.9f);

        // Inputs
        if (Input.GetKey (KeyCode.Space) && Camera.main.transform.position.y < 8f)
        {
            up = true;
            currentLerpTime = 0;
            lerpTime = 3f;
        }

        if (Input.GetKey (KeyCode.Space) && Camera.main.transform.position.y > 103f)
        {
            up = false;
            currentLerpTime = 0;
            lerpTime = 3f;
        }

        // When the camera is down (Lerp/Slerp)
        if (up == false)
        {

        currentLerpTime += Time.deltaTime;

        if (currentLerpTime >= lerpTime)
        {
            currentLerpTime = lerpTime;
        }

        float Perc = currentLerpTime / lerpTime;

        start = Camera.main.transform.position;
        Camera.main.transform.position = Vector3.Lerp (start, new Vector3 (Camera.main.transform.position.x, 105, Camera.main.transform.position.z), Perc);
        Camera.main.transform.rotation = Quaternion.Slerp (Camera.main.transform.rotation, RotationA, Perc);

        }


        // When the camera is up (Lerp/Slerp)

        if (up == true)
        {

        currentLerpTime += Time.deltaTime;

        if (currentLerpTime >= lerpTime)
        {
            currentLerpTime = lerpTime;
        }

        float Perc = currentLerpTime / lerpTime;

        end = Camera.main.transform.position;
        Camera.main.transform.position = Vector3.Lerp (end, new Vector3(Camera.main.transform.position.x, 6, Camera.main.transform.position.z), Perc);
        Camera.main.transform.rotation = Quaternion.Slerp (Camera.main.transform.rotation, RotationB, Perc);

        }
    }
}

I also tried another method for rotation, but nothing has changed:

Camera.main.transform.rotation = Quaternion.Slerp (Camera.main.transform.rotation, Quaternion.AngleAxis(179.9f, Vector3.forward), Perc)

Camera.main.transform.rotation = Quaternion.Slerp (Camera.main.transform.rotation, Quaternion.AngleAxis(359.9f, Vector3.forward), Perc)

How can i fix? Thanks in advance.


Solution

  • What your program does is alternating between two rotations, which account for half of sphere's rotation. To achieve your desired outcome, second rotation should be towards 0 angle. In your current program it rotates back to 360 angle.

    How it currently works:
    1. first rotation 359.9f -> 179.9f (float decreasing)
    2. second rotation 179.9f -> 359.9f (float increasing)
    3. (repeat from 1.)

    How you think it should be working:
    1. first rotation 359.9f -> 179.9f (float decreasing)
    2. second rotation 179.9f -> 0.0f (float decreasing and possibly resetting to 359.9f when value reaches zero)

    To follow your coding style, just add one more rotation:

    //Quaternions
    Quaternion RotationA = Quaternion.Euler (0, 0, 179.9f);
    Quaternion RotationB = Quaternion.Euler (0,0, 359.9f);
    Quaternion RotationC = Quaternion.Euler (0,0, 0.0f);
    

    and then change the other rotation to use RotationC

    // When the camera is up (Lerp/Slerp)
    
    if (up == true)
    {
        ...
    
        (Camera.main.transform.rotation, RotationC, Perc);    
    }
    

    and lastly the resetting back to the default value when rotation reaches zero:

    void Update () {
        if(Camera.main.transform.rotation == RotationC){
            Camera.main.transform.rotation = RotationB;
        }
    }