Camera rotation jitters after a certain threshold (video)

So I have this setup:

  • Camera rotation is clamped on the Y axis. It can only rotate from -75 to 75 degrees left and right, and its rotation is controlled by the mouse.

  • Player body can rotate around its Y axis, and its Y rotation value is added to -75 and 75 degree camera clamps in order to keep the camera rotation space in front of the player body. Example: If the player rotates 90 degrees on the Y axis, the clamp values would change to 15 and 165 degrees.

-The problem arises when the player body exceeds 359 degrees on the Y axis because camera clamp values jump from 284 and 434 back to -75 and 75, which causes a noticeable snap in camera movement.

Note the camera clamps (Limit L, Limit R) in the MouseLook script after 00:40

*The handleBodyRotation method just rotates the player body to face the red cube which is a child of the camera.

public class MouseLook : MonoBehaviour
{
    public Transform CameraBox;
    public Transform lookAtPivot;
    public Transform lookAtObject;
    public Transform playerBody;

    public float sensitivity;
    public float bodyRotSpeed;

    float xRotation = 0f;
    float yRotation = 0f;
    public float limitL;
    public float limitR;

    void Start()
    {
        Cursor.lockState = CursorLockMode.Locked;
    }

    void handleCamRotation()
    {
        float mouseX = Input.GetAxis("Mouse X") * sensitivity * Time.deltaTime;
        float mouseY = Input.GetAxis("Mouse Y") * sensitivity * Time.deltaTime;

        xRotation -= mouseY;
        xRotation = Mathf.Clamp(xRotation, -45, 35);

        yRotation += mouseX;
        yRotation = Mathf.Clamp(yRotation, limitL, limitR);

        //Handle and clamp Camera, lookAtPivot, and lookAtObject rotation
        transform.rotation = Quaternion.Euler(xRotation, yRotation, 0f);

        //Handle left limit and right limit
        limitL = -75 + playerBody.transform.rotation.eulerAngles.y;
        limitR = 75 + playerBody.transform.rotation.eulerAngles.y;
       
    }

    void handleBodyRotation()
    {
        Quaternion targetRotation = Quaternion.Euler(playerBody.transform.rotation.eulerAngles.x, lookAtObject.transform.rotation.eulerAngles.y, playerBody.transform.rotation.eulerAngles.z);
        playerBody.transform.localRotation = Quaternion.Lerp(playerBody.transform.localRotation, targetRotation, bodyRotSpeed * Time.deltaTime);
    }

    void Update()
    {
        //Camera Rotation (clamped)
        handleCamRotation();

        //Body Rotation
        if (Input.GetKey(KeyCode.W))
        {
            handleBodyRotation();
        }
    }
}

Never read from .eulerAngles properties… they are subject to gimbal lock, which is precisely what you’re seeing.

Instead track and adjust your own notions of rotation in float variables and drive them to the transform.rotation

1 Like

Hey, thank you for taking your time to respond to my post!

Yeah, I had my suspicions regarding gimbal lock since that’s the cause of the majority of rotation problems people were encountering on forums… Others usually recommended the quaternion approach, although I’m unsure on how would I go about fixing this with quats since I need to add the value of player body Y rotation to my left and right clamp limits.

If it’s not a problem, could you correct my lines to not use .eulerAngles for incrementing the clamp limits?

It’s not really possible. Part of the problem is the code, the other part is how your hierarchy is set up, which may need an extra Transform parented through things to handle the rotation you want. Work through some other look and turn and gaze tutorials for more insight into extra Transforms in your hierarchy. Here’s also an example of a gun turret hierarchy individually controlled on specific axes:

https://discussions.unity.com/t/783469/2

1 Like

Thank you, I will look into that.