Why is my mouse look-around stuttering?

As a learning exercise I am writing a MouseLookAround script, which is attached to my “Player” GameObject (which is the parent of my camera).

[74686-new-unity-project.zip|74686]

using UnityEngine;
using System;

public class MouseLook : MonoBehaviour {
    [Flags]
    public enum RotationAxes
    {
        None,
        LeftAndRight,
        UpAndDown,
        Both = LeftAndRight + UpAndDown
    }

    public RotationAxes axes = RotationAxes.Both;
    public float horizontalSensitivity = 9f;
    public float verticalSensitivity = 9f;
    public float verticalMinimum = -45f;
    public float verticalMaximum = 45f;

    void OnGUI()
    {
        GUI.TextArea(new Rect(0, 0, 100, 20), "" + transform.localEulerAngles.x);
    }


    // Update is called once per frame
    void Update () {

        if ((axes & RotationAxes.LeftAndRight) != 0)
        {
            float yaw = Input.GetAxis("Mouse X") * horizontalSensitivity;
            transform.Rotate(0, yaw, 0);
        }

        if ((axes & RotationAxes.UpAndDown) != 0)
        {
            float yaw = transform.localEulerAngles.y;
            float pitch = -Input.GetAxis("Mouse Y") * verticalSensitivity;
            //pitch = Mathf.Clamp(pitch, verticalMinimum, verticalMaximum);
            pitch += transform.localEulerAngles.x;
            transform.localEulerAngles = new Vector3(pitch, yaw, 0);
        }
    }
}

When I run this project and move my mouse up/down I notice that the angle when looking down is limited to 90, and my angle when looking up is limited to 270 (even though the Mathf.Clamp is commented out).

In addition, when Unity clamps these angles it does so with a certain amount of variability. So, when my view angle (pitch) is already 90 and I move my mouse down the camera angle will change to something like 89.98, causing the scene to jump all over the place.

Could someone please explain to me why it is limiting my range, and why this stuttering occurs?

Look at [this][1] [1]: https://en.wikipedia.org/wiki/Gimbal_lock

1 Answer

1

The solution was to set transform.localEulerAngles rather than using transform.rotate, and to have a class member to store the pitch rather than modifying the localEurlerAngles.x

using UnityEngine;
using System;

public class MouseLook : MonoBehaviour {
    [Flags]
    public enum RotationAxes
    {
        None,
        LeftAndRight,
        UpAndDown,
        Both = LeftAndRight + UpAndDown
    }

    public RotationAxes axes = RotationAxes.Both;
    public float horizontalSensitivity = 9f;
    public float verticalSensitivity = 9f;
    public float verticalMinimum = -45f;
    public float verticalMaximum = 45f;

    float pitch;

    // Update is called once per frame
    void Update () {
        float yaw = transform.localEulerAngles.y;
        if ((axes & RotationAxes.LeftAndRight) != 0)
            yaw += Input.GetAxis("Mouse X") * horizontalSensitivity;

        if ((axes & RotationAxes.UpAndDown) != 0)
        {
            float pitchDelta = -Input.GetAxis("Mouse Y") * verticalSensitivity;
            pitch += pitchDelta;
            pitch = Mathf.Clamp(pitch, verticalMinimum, verticalMaximum);
        }
        transform.localEulerAngles = new Vector3(pitch, yaw, 0);
    }
}

Now my member “pitch” can vary between the verticalMimimum and verticalMaximum (-45 to 45), and setting this value will result in looking horizontally forward + a number in that range

Hey, I noticed that the pitch and yaw change in 0.25-degree increments. Do you know why this happens? Type float should achieve better resolution than that for sure.