Coding noob struggles to implement first-Person camera rotation.


I am having problems on how i limit the Y axis to a certain degrees. What i mean is: When i look forward, i want the Y axis to be limited to a total of 40 degrees, so that i am not capable of looking straight up/straight down to my feet and further.

I would really appriciate it if someone could give me some help on how to make this possible, thank you.

My script (c#):

using UnityEngine;
using System.Collections;

public class CamMouseLook : MonoBehaviour {

Vector2 mouseLook;
Vector2 smoothV;
public float sensitivity = 10f;
public float smoothing = 2f;

GameObject character;

void Start()
    character = this.transform.parent.gameObject;

void Update()
    var md = new Vector2(Input.GetAxisRaw("Mouse X"), Input.GetAxisRaw("Mouse Y"));

    md = Vector2.Scale(md, new Vector2(sensitivity * smoothing, sensitivity * smoothing));
    smoothV.x = Mathf.Lerp(smoothV.x, md.x, 1f / smoothing);
    smoothV.y = Mathf.Lerp(smoothV.y, md.y, 1f / smoothing);
    mouseLook += smoothV;

    transform.localRotation = Quaternion.AngleAxis(-mouseLook.y, Vector3.right);
    character.transform.localRotation = Quaternion.AngleAxis(mouseLook.x, character.transform.up);


The Solution:

With your current setup, this is as simple as using if statements, or the handy builtin Mathf.Clamp function.

To clamp some value X between A and B, you can do this:

float x, a, b; //Assuming A<=B

}else if(x>b){

This is actually equivalent to a nice helper function in the unity library, used like this:

float x, a, b; //Again, a<=b

x = Mathf.Clamp(x,a,b);

Both of these snippets do the same thing. In fact, while I’m not 100% certain, the second method probably just does the first one behind-the-scenes. So in your code, you could, say, define:

public float yMin, yMax;

And then later, in Update():

mouseLook += smoothV;//Your code, so you can see where to put it
mouseLook.y = Mathf.Clamp(mouseLook.y,yMin,yMax); //The actual clamp

Big Important Sidenote

There are a couple of other things I’m noticing in your camera script that are going to cause you problems. This isn’t part of the main question but, since you said you were new to coding, you might want to know these since they’re pretty common mistakes. (Apologies for poor formatting, lists seem to break code-formatting)

----1: Your mouse sensitivity right now is framerate dependent. You need to include md *= Time.deltaTime to correct this. See This Page for more details.

----2: Your smoothing is a bit wonky. Your smoothing is A: framerate dependent, just like pt 1, and B: your smoothing is on the velocity, which can feel a bit weird (your camera won’t end up where you expect if you move the mouse around a lot.) The fix for this is to instead do your interpolation on the target position instead. Consider the following code:

Vector2 md = new Vector2(Input.GetAxisRaw("Mouse X"),Input.GetAxisRaw("Mouse Y"));
    md *= sensitivity * Time.deltaTime; //Notice the removal of smoothing term here and the introduction of the Time.deltaTime term
    targetLook = mouseLook+md; //I created this targetLook Vector2 here. This can replace smoothV, I just wanted a more descriptive name
    targetLook.y = Mathf.Clamp(targetLook.y,yMin,yMax); //The clamping you wanted. Make sure this is applied to the target, not the actual, rotation
    //Now, the interpolation
    //Using Vector2.Lerp is easier than 2 Mathf.Lerps
    //Note the use of Time.deltaTime
    //Also note that this happens to the ROTATION, not VELOCITY
    mouseLook = Vector2.Lerp(mouseLook,targetLook,Time.deltaTime/smoothing);
    //And then your rotation setting code:
    transform.localRotation = Quaternion.AngleAxis(-mouselook.y,Vector3.right);
    character.transform.localRotation = Quaternion.AngleAxis(mouselook.x,character.transform.up);

Hoped this helps, and good luck on your project!