- Home /
Coding noob struggles to implement first-Person camera rotation.
HI!
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);
}
}
Answer by Zarenityx · Jun 26, 2019 at 08:33 PM
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
if(x<a){
x=a;
}else if(x>b){
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
//etc...
Big Important Sidenote
here 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!
Hey, sorry for my late reaction! Thanks for the extra notes, i really Appriciate it! The code you have given me has worked for the most part, the clamping works perfectly, although there is one big problem... I am not sure what's causing it, but whenever i play test it the camera keeps shaking like it's having a stroke the moment i move my mouse! It says: "transform.localRotation assign attempt for 'Character' is not valid. Input rotation is { NaN, NaN, NaN, NaN }. UnityEngine.Transform:set_localRotation(Quaternion)" Do you now what that means? I have no clue 0_0
This is the script i currently have:
using UnityEngine;
using System.Collections;
public class Cam$$anonymous$$ouseLook : $$anonymous$$onoBehaviour
{
public float y$$anonymous$$in, y$$anonymous$$ax;
float x, a, b;
Vector2 mouseLook;
Vector2 targetLook;
public float sensitivity = 10f;
public float smoothing = 2f;
GameObject character;
void Start()
{
character = this.transform.parent.gameObject;
}
void Update()
{
if (x < a)
{
x = a;
}
else if (x > b)
{
x = b;
}
mouseLook += targetLook;
targetLook.y = $$anonymous$$athf.Clamp(targetLook.y, y$$anonymous$$in, y$$anonymous$$ax);
Vector2 md = new Vector2(Input.GetAxisRaw("$$anonymous$$ouse X"), Input.GetAxisRaw("$$anonymous$$ouse Y"));
md *= sensitivity * Time.deltaTime;
targetLook = mouseLook + md;
targetLook.x = $$anonymous$$athf.Lerp(targetLook.x, md.x, 1f / smoothing);
targetLook.y = $$anonymous$$athf.Lerp(targetLook.y, md.y, 1f / smoothing);
mouseLook = Vector2.Lerp(mouseLook, targetLook, Time.deltaTime / smoothing);
transform.localRotation = Quaternion.AngleAxis(-mouselook.y, Vector3.right);
character.transform.localRotation = Quaternion.AngleAxis(mouselook.x, character.transform.up);
}
}
Hey, sorry I got back so late too. I generally write code directly into the submission box so it's entirely possible that the code as is doesn't compile or work quite as intended. Code given is intended as a guideline or visual aid, but not to be copy-pasted. (It's always a bad idea to copy-paste code from the internet anyway.) Regardless, here's a few things I noticed:
Check if your smoothing is 0 or near 0. This can cause issues. If you want to be able to turn off smoothing, then use an if statement to bypass the Vector2.Lerp.
Get rid of the two lines with the $$anonymous$$athf.Lerp in them. Those two lines are superseded by the Vector2.Lerp line anyway, since they were framerate-dependent. The
targetLook = mouseLook+md
line and the $$anonymous$$athf.Clamp are the ONLY things that should modify targetLook.$$anonymous$$ove the clamping to AFTER the lines that adds md. This should fix some jittering. The issue it that it's being clamped, then edited, meaning it can actually go past the clamp and then later get re-clamped, causing a jarring shaking effect.
You have an if statement included that does nothing. Looks like you copy-pasted my example code of how clamping works. This was written as an example, and actually does nothing useful in your script.
Can't be sure, but it looks like you're copy-pasting. If you are, DON'T. It will make it significantly harder to figure out what's going on down the line, and even if you end up making it work, you'll learn less from it. Ins$$anonymous$$d, look through the code and figure out what it's doing, then write it yourself. This will let you learn how that code functions. Treat internet code snippets as pictures in an instruction manual, not as magic potion ingredients.