Search Unity

Mouse Look Issues

Discussion in 'Scripting' started by Thethispointer, Oct 1, 2020.

  1. Thethispointer

    Thethispointer

    Joined:
    Feb 11, 2018
    Posts:
    105
    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!

    1. I rotate the player's game object on the Y axis.
    2. I rotate the gameObject (to my understanding...) on the X axis, which is seemingly working good...
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class myMouseLook : MonoBehaviour
    6. {
    7.     public float mouseSensitivity = 100f;
    8.  
    9.     public Transform playerBody;
    10.  
    11.     float xRotation = 0f;
    12.  
    13.     // Start is called before the first frame update
    14.     void Start()
    15.     {
    16.         Cursor.lockState = CursorLockMode.Locked;
    17.     }
    18.  
    19.     // Update is called once per frame
    20.     void Update()
    21.     {
    22.         float mouseX = Input.GetAxis("Mouse X") * mouseSensitivity * Time.deltaTime;
    23.         float mouseY = Input.GetAxis("Mouse Y") * mouseSensitivity * Time.deltaTime;
    24.  
    25.         xRotation -= mouseY;
    26.         xRotation = Mathf.Clamp(xRotation, -90f, 90f);
    27.  
    28.         transform.localRotation = Quaternion.Euler(xRotation, 0f, 0f);
    29.         playerBody.Rotate(Vector3.up * mouseX);
    30.     }
    31. }
    32.  


    my rotation side to side isn't working. Can anyone help me out? Thank you! :)
     
  2. orionsyndrome

    orionsyndrome

    Joined:
    May 4, 2014
    Posts:
    3,108
    Code (csharp):
    1. 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.
     
  3. orionsyndrome

    orionsyndrome

    Joined:
    May 4, 2014
    Posts:
    3,108
    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.
     
    Thethispointer likes this.
  4. orionsyndrome

    orionsyndrome

    Joined:
    May 4, 2014
    Posts:
    3,108
    (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.
     
  5. Thethispointer

    Thethispointer

    Joined:
    Feb 11, 2018
    Posts:
    105
    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!
     
  6. orionsyndrome

    orionsyndrome

    Joined:
    May 4, 2014
    Posts:
    3,108
    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.
     
    Thethispointer likes this.
  7. Thethispointer

    Thethispointer

    Joined:
    Feb 11, 2018
    Posts:
    105
    Thank you! I will post an update when I work on this today!
     
  8. Thethispointer

    Thethispointer

    Joined:
    Feb 11, 2018
    Posts:
    105
    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):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class myMouseLook : MonoBehaviour
    6. {
    7.     public float mouseSensitivity = 100f;
    8.  
    9.     public Transform playerBody;
    10.  
    11.     float xRotation = 0f;
    12.  
    13.     // Start is called before the first frame update
    14.     void Start()
    15.     {
    16.         Cursor.lockState = CursorLockMode.Locked;
    17.     }
    18.  
    19.     // Update is called once per frame
    20.     void Update()
    21.     {
    22.         float mouseX = Input.GetAxis("Mouse X") * mouseSensitivity * Time.deltaTime;
    23.         float mouseY = Input.GetAxis("Mouse Y") * mouseSensitivity * Time.deltaTime;
    24.  
    25.         xRotation -= mouseY; // TODO handle unwrapping
    26.         xRotation = Mathf.Clamp(xRotation, -90f, 90f);
    27.  
    28.         transform.localRotation = Quaternion.Euler(xRotation, 0f, 0f);
    29.         playerBody.Rotate(Vector3.up * mouseX);
    30.     }
    31. }
    32.  
    Character Motor thanks to Unity Documentation
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class characterControllerMoveExample : MonoBehaviour
    6. {
    7.     private CharacterController controller;
    8.     private Vector3 playerVelocity;
    9.     private bool groundedPlayer;
    10.     private float playerSpeed = 2.0f;
    11.     private float jumpHeight = 1.0f;
    12.     private float gravityValue = -9.81f;
    13.  
    14.     // Start is called before the first frame update
    15.     void Start()
    16.     {
    17.         controller = gameObject.AddComponent<CharacterController>();
    18.     }
    19.  
    20.     // Update is called once per frame
    21.     void Update()
    22.     {
    23.         groundedPlayer = controller.isGrounded;
    24.         if (groundedPlayer && playerVelocity.y < 0)
    25.         {
    26.             playerVelocity.y = 0f;
    27.         }
    28.  
    29.         Vector3 move = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));
    30.         controller.Move(move * Time.deltaTime * playerSpeed);
    31.  
    32.         if (move != Vector3.zero)
    33.         {
    34.             gameObject.transform.forward = move;
    35.         }
    36.  
    37.         // Changes the height position of the player..
    38.         if (Input.GetButtonDown("Jump") && groundedPlayer)
    39.         {
    40.             playerVelocity.y += Mathf.Sqrt(jumpHeight * -3.0f * gravityValue);
    41.         }
    42.  
    43.         playerVelocity.y += gravityValue * Time.deltaTime;
    44.         controller.Move(playerVelocity * Time.deltaTime);
    45.     }
    46. }
    47.  
     
  9. Thethispointer

    Thethispointer

    Joined:
    Feb 11, 2018
    Posts:
    105
    Also, if anyone can help me configure my movement to not lock my x axis rotation, that would be amazing!
     
  10. nightwolf123501

    nightwolf123501

    Joined:
    Oct 9, 2020
    Posts:
    1
    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.
     
  11. orionsyndrome

    orionsyndrome

    Joined:
    May 4, 2014
    Posts:
    3,108
    my remark had nothing to do with the sign of the operation.
     
  12. Talal88

    Talal88

    Joined:
    Jun 25, 2021
    Posts:
    7
    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
     
  13. orionsyndrome

    orionsyndrome

    Joined:
    May 4, 2014
    Posts:
    3,108
    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):
    1. var mouseX = Input.GetAxis("Mouse X"); // leave the input as is
    2. var speed = maximumSpeed * (mouseX * mouseSensitivity); // scale the effect the input has to regulate speed
    3. 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.
     
  14. Bunny83

    Bunny83

    Joined:
    Oct 18, 2010
    Posts:
    3,992
    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.
     
  15. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,697
    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.
     
  16. Talal88

    Talal88

    Joined:
    Jun 25, 2021
    Posts:
    7
    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