Why is my camera rotation clamp not working?

I’m just trying to make a script that locks the players X rotation between 60 and -60. Looking down at X 60 works just fine, but when I looks up at X -60 the camera goes berserk for seemingly no reason. Please help!

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerLook : MonoBehaviour
{
    public Transform playerBody;
    public float mouseSensitivity;

    float xAxisClamp = 0.0f;

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

    void Update()
    {
        RotateCamera();
    }

    void RotateCamera()
    {
        float mouseX = Input.GetAxis("Mouse X");
        float mouseY = Input.GetAxis("Mouse Y");

        float rotAmountX = mouseX * mouseSensitivity;
        float rotAmountY = mouseY * mouseSensitivity;

        xAxisClamp -= rotAmountY;

        Vector3 targetRotCam = transform.rotation.eulerAngles;
        Vector3 targetRotBody = playerBody.rotation.eulerAngles;

        targetRotCam.x -= rotAmountY;
        targetRotCam.z = 0;

        targetRotBody.y += rotAmountX;

        if(xAxisClamp > 60)
        {
            xAxisClamp = 60;
            targetRotCam.x = 60;
        }
        else if(xAxisClamp < -60)
        {
            xAxisClamp = -60;
            targetRotCam.x = 240;
        }

        transform.rotation = Quaternion.Euler(targetRotCam);
        playerBody.rotation = Quaternion.Euler(targetRotBody);
    }
}

You are getting EulerAngles from the rotation, which gives a different result in my experience. I’ve seen the description about it in the manual.
Try this, from my experiments it gives a different result instead of:

Vector3 targetRotCam = transform.rotation.eulerAngles;

Try:

Vector3 targetRotCam = transform.eulerAngles;

I don’t know if it will work in your case, I just know I was copying rotation to another object and it kept reversing until I used eulerAngles from the transform. If it’s not working the way you want, have it print the angles in debug and you’ll figure it out.
The reason given in the manual is that a eulerAngle from a quaternion only goes up to 180 degrees instead of 360. In my case, when I was copying a revolving object, it would copy half way and then reverse direction from rotation, but would do an exact copy when getting eulerAngles directly from the transform.

This did not work

If you’re driving both values manually yourself (as in other forces aren’t in play), it’s much easier to store the values separately as pitch and yaw, clamp them and rebuild the rotation every frame.

float pitch, yaw; // up in the class

void Update()
{
   pitch = Mathf.Clamp(pitch + Input.GetAxis("Mouse Y"), -60, 60);
   yaw += Input.GetAxis("Mouse X");

   transform.rotation = Quaterion.Euler(pitch, yaw, 0f);
}

No rollover, no math to unfold your Quaternions properly, etc.

I just typed this here but you get the idea.

1 Like

Alright this did succesfully clamp the camera’s X rotation (up/down) to between -60 and 60. But now i’m having another problem. Basically the camera look script also controls the player body gameobject, so the player spins around with the camera (which is what literally every first person game does). But with this updated script you’ve provided me it’s producing spastic Y rotation (left/right) movement and I’m not sure why; it jumps around slightly as I spin around. The camera is a child of the player gameobject by the way.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerLook : MonoBehaviour
{
    public Transform playerBody;
    public float mouseSensitivity;

    float pitch;
    float yaw;

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

    void Update()
    {
        RotateCamera();
    }

    void RotateCamera()
    {
        float mouseX = Input.GetAxis("Mouse X");
        float mouseY = Input.GetAxis("Mouse Y");
        float rotAmountX = mouseX * mouseSensitivity;
        float rotAmountY = mouseY * mouseSensitivity;
        Vector3 targetYawBody = playerBody.eulerAngles;
        targetYawBody.y += rotAmountX;

        pitch = Mathf.Clamp(pitch - rotAmountY, -60f, 60f);
        yaw += rotAmountX;

        transform.rotation = Quaternion.Euler(pitch, yaw, 0f);
        playerBody.rotation = Quaternion.Euler(targetYawBody);
    }
}

@VileGoo , I’m not a hundred percent sure on this one since I am a beginner to this all. But make an open variable public Camera cam and rewrite it so that the input rotation affects the camera instead of the whole body.