Hello! I am perfecting my own mouseLook script, and right now I am finishing up a tutorial that is helping me learn about controlling the camera with the mouse. Please help me understand why my mouseLook isn't working like Brackey's! I rotate the player's game object on the Y axis. I rotate the gameObject (to my understanding...) on the X axis, which is seemingly working good... Code (CSharp): using System.Collections; using System.Collections.Generic; using UnityEngine; public class myMouseLook : MonoBehaviour { public float mouseSensitivity = 100f; public Transform playerBody; float xRotation = 0f; // Start is called before the first frame update void Start() { Cursor.lockState = CursorLockMode.Locked; } // Update is called once per frame void Update() { float mouseX = Input.GetAxis("Mouse X") * mouseSensitivity * Time.deltaTime; float mouseY = Input.GetAxis("Mouse Y") * mouseSensitivity * Time.deltaTime; xRotation -= mouseY; xRotation = Mathf.Clamp(xRotation, -90f, 90f); transform.localRotation = Quaternion.Euler(xRotation, 0f, 0f); playerBody.Rotate(Vector3.up * mouseX); } } my rotation side to side isn't working. Can anyone help me out? Thank you!
Code (csharp): xRotation -= mouseY why is everybody doing this?? please kindly explain what did you expect this code would do? at this point I'm thinking there is some kind of Brackeys video that has this as a typo or something.
Ok I take it back, they truly do it like this, not really caring for any of the implications down the line. I wouldn't do it like this in a million years, but ok, this seems to be a copy/paste of what Brackeys does anyway. Now pay special attention to where's what. You need to have a First Person Player as a main object, with a player model object and camera set as its children. The First Person Player is supposed to have Character Controller on it, and the camera is supposed to have this script you've shown. If you do it like this, THEN it should do what it does in the Brackeys video. From your video it's not obvious where your scripts are, and the camera seems to belong to some other object, that's at least what I'm seeing.
(No wonder Brackeys has bailed the scene btw. Throngs of people want to know their location.) Btw this is the actual Brackeys video, for the reference.
Next time I will include a Brackey's Disclaimer LOL! YES I want to understand his example! AND, if you want to be satisfied I prefer the charactercontroller.move found in the documentation! I am understanding Brackey's not exactly copy and pasting with intent to completely use the code. This part of the reply is not specifically toward anyone. To who replied here, great reply! Thank you!
Sorry if I was a bit harsh, it's because I've seen that particular code for at least a couple of times now, and always I'm a little baffled with that particular line. I have nothing against you trying to understand how it works. Why I wouldn't do that particular line like that is because that value tends to rotate "indefinitely" meaning that it will surely end up becoming -123873574.343535897 if you're constantly rotating in the same direction (which could happen). Obviously, this isn't an issue for beginners trying to make this feature to work and prototype some FPS, but it can become a source of hard to track jittery motion due to floating point imprecisions that will accumulate over time. Apart from that, it leads anyone sufficiently advanced to look at it and think "hmm" -- that line is a needless attention grabber for people who know how to code. Because this accumulation isn't particularly well handled, it definitely looks like a typo or an oversight. If I wanted to make this intentionally, I would intentionally write it as xRotation = xRotation - mouseY or xRotation -= mouseY; // TODO handle unwrapping. Yadda yadda programmer's blues. Hopefully you've set it up to work.
Okay, I am going to try to give a detailed reply. I have a 3D primitive cube as the ground, plain material colorized green, kinematic enabled, box collider, rigidbody, freeze position and rotation on all three axis. I have some objects with no colliders to render something to look at. I have a Game Object (Character Brain) with two children, camera and the character's model. script on camera and parent game object Mouse Look on Camera, credit Brackey's YouTube Code (CSharp): using System.Collections; using System.Collections.Generic; using UnityEngine; public class myMouseLook : MonoBehaviour { public float mouseSensitivity = 100f; public Transform playerBody; float xRotation = 0f; // Start is called before the first frame update void Start() { Cursor.lockState = CursorLockMode.Locked; } // Update is called once per frame void Update() { float mouseX = Input.GetAxis("Mouse X") * mouseSensitivity * Time.deltaTime; float mouseY = Input.GetAxis("Mouse Y") * mouseSensitivity * Time.deltaTime; xRotation -= mouseY; // TODO handle unwrapping xRotation = Mathf.Clamp(xRotation, -90f, 90f); transform.localRotation = Quaternion.Euler(xRotation, 0f, 0f); playerBody.Rotate(Vector3.up * mouseX); } } Character Motor thanks to Unity Documentation Code (CSharp): using System.Collections; using System.Collections.Generic; using UnityEngine; public class characterControllerMoveExample : MonoBehaviour { private CharacterController controller; private Vector3 playerVelocity; private bool groundedPlayer; private float playerSpeed = 2.0f; private float jumpHeight = 1.0f; private float gravityValue = -9.81f; // Start is called before the first frame update void Start() { controller = gameObject.AddComponent<CharacterController>(); } // Update is called once per frame void Update() { groundedPlayer = controller.isGrounded; if (groundedPlayer && playerVelocity.y < 0) { playerVelocity.y = 0f; } Vector3 move = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical")); controller.Move(move * Time.deltaTime * playerSpeed); if (move != Vector3.zero) { gameObject.transform.forward = move; } // Changes the height position of the player.. if (Input.GetButtonDown("Jump") && groundedPlayer) { playerVelocity.y += Mathf.Sqrt(jumpHeight * -3.0f * gravityValue); } playerVelocity.y += gravityValue * Time.deltaTime; controller.Move(playerVelocity * Time.deltaTime); } }
Also, if anyone can help me configure my movement to not lock my x axis rotation, that would be amazing!
if you do xRotation += mouseY, up and down looking is inverted so to prevent this we do xRotation -= mouseY so that up and down controls aren't inverted.
Hey @orionsyndrome , I'm also caught red-handed using Brackey's code. A compounding issue that I am facing in regards to the code is that the mouse sensitivity is different in the editor vs in the build. I'm trying to debug it but can't seem to figure it out. For instance, attempting to change: float mouseX = Input.GetAxis("Mouse X") * mouseSensitivity * Time.deltaTime; to float mouseX = Input.GetAxis("Mouse X") * mouseSensitivity * Time.time; That bumps the sensitivity way up, and when you try to decrease the variable's value it becomes jittery. Could you provide a tentative solution to my problem, would really appreciate it. Cheers
First, you're not supposed to multiply the input at all. The input is what it is, it is already distributed over time, because it's hardware-dependent. Second, you never multiply with Time.time, that's a number that only ever increases over time, as it measures time since the beginning of the game. DeltaTime is a measurement of time since the last frame, making it useful to proportionately scale the effect of any input. Think about all of this from scratch, don't just blindly copy paste. You have some input, and you have your frames distributed over time. Imagine a frame rate of 60 FPS, then you'd have a delta time of 1/60 = 16.66 milliseconds. Consider this, if 60 FPS is in frames/second, then delta time is seconds/frame. The speed of something in your game is expressed in units/second, but what you really want is units/frame because Update works in every frame, not per second. This is why we multiply speed with delta time. You start with S [unit/sec] and scale that with delta time. Watch what happens with the units. S [unit/sec] * D [sec/frame] [sec] units cancel out and what you're left with is S*D [unit/frame] Now you want to regulate this theoretical speed with your input. Ideally it's 1, but you can also have a half-input on your analog joystick. As a separate concern, you also want this "sensitivity" which is literally an arbitrary scale on the input to make it bigger or smaller. So what you end up with is this Code (csharp): var mouseX = Input.GetAxis("Mouse X"); // leave the input as is var speed = maximumSpeed * (mouseX * mouseSensitivity); // scale the effect the input has to regulate speed var movementPerFrame = speed * Time.deltaTime; // convert units/second to units/frame Which isn't that much different from what you already had. So if something doesn't work as expected, a) make sure you don't multiply with Time.time because that doesn't make any sense, b) your problems lie somewhere else.
You shouldn't multiply the mouse delta by Time.time nor by Time.deltaTime. The mouse delta is already a frame based measure as it updates once per frame. The mouse delta isn't a movement speed per second. It's literally how far the mouse moved (in virtual units) since the last frame. So keep time out of the question here, you're just making it worse and actually make it framerate dependent that way. Lets say moving the mouse 50mm in the real world equates to say "500 units". Without any fancy acceleration if the user manages to move the mouse that distance between two frames, GetAxis would report that value of 500. However if the user moves the mouse more slowly the same distance so that 10 frames have passed, GetAxis would have reported a value of about 50 each frame which again accumulates to 500. So you really need to remove that deltaTime (and of course Time.time which makes no sense at all ^^) and your issues should be fixed.
Look, before anyone wastes another MILLISECOND on this tutorial, STOP. Delete the code. The tutorial is COMPLETELY broken. Here's why: I wrote about this before: the Unity example code in the API no longer jumps reliably. If you call .Move() twice in one single frame, the grounded check may fail. I reported it to Unity via their docs feedback in October 2020. Apparently it is still broken: https://docs.unity3d.com/ScriptReference/CharacterController.Move.html Here is a work-around: https://forum.unity.com/threads/how...racter-movement-in-unity.981939/#post-6379746 I recommend you also go to that same documentation page and ALSO report that the code is broken. When you report it, you are welcome to link the above workaround. One day the docs might get fixed. If you would prefer something more full-featured here is a super-basic starter prototype FPS based on Character Controller (BasicFPCC): https://forum.unity.com/threads/a-basic-first-person-character-controller-for-prototyping.1169491/ That one has run, walk, jump, slide, crouch... it's crazy-nutty!! This particular Brackey's tutorial should be removed. It is giving out faulty broken information and wasting everybody's time here.
So what I did was remove the Time.DeltaTime multiplication altogether. The other main thing that ended up solving the issue is making the sensitivity variable private. I appreciate everyone´s input. Thanks a lot for the detailed responses. Cheers