Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

Character Controller is Choppy

Discussion in 'Scripting' started by spencer_white, Dec 22, 2016.

  1. spencer_white

    spencer_white

    Joined:
    Nov 9, 2015
    Posts:
    37
    Hi, I am using the following code as a first person character controller:

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class CharacterController : MonoBehaviour {
    5.  
    6.     public float mouseSpeedX;
    7.     public float mouseSpeedY;
    8.     public float playerMoveSpeed;
    9.     public float jumpForce;
    10.  
    11.     float verticalLookRotation;
    12.     Rigidbody rb;
    13.     Ray ray;
    14.  
    15.     bool isGrouded() {
    16.         Vector3 pos = transform.position; pos.y -= 0.98f;
    17.         Collider[] cols = Physics.OverlapSphere(pos, 0.2f);
    18.         if (cols.Length > 1) return true;
    19.         else return false;
    20.     }
    21.  
    22.     void Start() {
    23.         Cursor.lockState = CursorLockMode.Locked;
    24.         Cursor.visible = false;
    25.         rb = GetComponent<Rigidbody>();
    26.     }
    27.  
    28.     void Update() {
    29.  
    30.         if (Input.GetKeyDown(KeyCode.Escape)) {
    31.             Cursor.lockState = CursorLockMode.None;
    32.             Cursor.visible = true;
    33.         }
    34.         if (Input.GetMouseButtonDown(0)) {
    35.             Cursor.lockState = CursorLockMode.Locked;
    36.             Cursor.visible = false;
    37.         }
    38.  
    39.         Camera.main.transform.localPosition = new Vector3(0f, 0.75f, 0f);
    40.         transform.Rotate(Vector3.up * Input.GetAxis("Mouse X") * Time.deltaTime * mouseSpeedX);
    41.         verticalLookRotation += Input.GetAxis("Mouse Y") * Time.deltaTime * mouseSpeedY;
    42.         verticalLookRotation = Mathf.Clamp(verticalLookRotation, -90, 75);
    43.         Camera.main.transform.localEulerAngles = Vector3.left * verticalLookRotation;
    44.  
    45.         rb.velocity = new Vector3(0f, rb.velocity.y, 0f);
    46.         float finalMoveSpeed = (Input.GetKey(KeyCode.LeftShift)) ? playerMoveSpeed * 1.5f : playerMoveSpeed;
    47.  
    48.         Vector3 movement = transform.TransformDirection(new Vector3(Input.GetAxis("Horizontal"), 0f, Input.GetAxis("Vertical")).normalized);
    49.        
    50.         rb.MovePosition(transform.position + movement * finalMoveSpeed);
    51.        
    52.         if (Input.GetKey(KeyCode.Space) && isGrouded()) rb.velocity = new Vector3(rb.velocity.x, jumpForce, rb.velocity.z);
    53.     }
    54. }
    Moving the player is relatively smooth, and so is looking around. I noticed, however, that when I am moving and rotating, like, orbiting around a cube while looking at it, the camera gets very choppy. Does anyone have a similar problem, or possible solution? Thanks.
     
  2. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,380
    Use LateUpdate to update the camera. This way before the screen renders the camera it's updated to the most recent position.
     
  3. TaleOf4Gamers

    TaleOf4Gamers

    Joined:
    Nov 15, 2013
    Posts:
    825
    I am still bored so I took the liberty to clean up your code and (possibly) fix your issue.
    (Im no pro with player controllers so it may not be perfect just a little bit of updating needed)
    As @lordofduct said above, use LateUpdate for the camera.
    If im doing something wrong let me know, feedback is good.

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. public class CharacterController : MonoBehaviour {
    4.     public float mouseSpeedX;
    5.     public float mouseSpeedY;
    6.     public float playerMoveSpeed;
    7.     public float jumpForce;
    8.     float verticalLookRotation;
    9.     Rigidbody rb;
    10.     Ray ray;
    11.     bool isGrouded() {
    12.         Vector3 pos = transform.position; pos.y -= 0.98f;
    13.         Collider[] cols = Physics.OverlapSphere(pos, 0.2f);
    14.  
    15.         if (cols.Length > 1)
    16.             return true;
    17.         else
    18.             return false;
    19.     }
    20.     void Start() {
    21.         LockCursor();
    22.         rb = GetComponent<Rigidbody>();
    23.     }
    24.  
    25.     void LockCursor()
    26.     {
    27.         Cursor.lockState = CursorLockMode.Locked;
    28.         Cursor.visible = false;
    29.     }
    30.  
    31.     void UnlockCursor()
    32.     {
    33.         Cursor.lockState = CursorLockMode.None;
    34.         Cursor.visible = true;
    35.     }
    36.     void Update() {
    37.         if (Input.GetKeyDown(KeyCode.Escape))
    38.             UnlockCursor();
    39.         if (Input.GetMouseButtonDown(0))
    40.             LockCursor();
    41.         UpdatePlayer();
    42.      
    43.         if (Input.GetKey(KeyCode.Space) && isGrouded())
    44.             rb.velocity = new Vector3(rb.velocity.x, jumpForce, rb.velocity.z);
    45.     }
    46.  
    47.     void UpdatePlayer()
    48.     {
    49.         transform.Rotate(Vector3.up * Input.GetAxis("Mouse X") * Time.deltaTime * mouseSpeedX);
    50.         verticalLookRotation += Input.GetAxis("Mouse Y") * Time.deltaTime * mouseSpeedY;
    51.         verticalLookRotation = Mathf.Clamp(verticalLookRotation, -90, 75);
    52.         rb.velocity = new Vector3(0f, rb.velocity.y, 0f);
    53.         float finalMoveSpeed = (Input.GetKey(KeyCode.LeftShift)) ? playerMoveSpeed * 1.5f : playerMoveSpeed;
    54.         Vector3 movement = transform.TransformDirection(new Vector3(Input.GetAxis("Horizontal"), 0f, Input.GetAxis("Vertical")).normalized);
    55.      
    56.         rb.MovePosition(transform.position + movement * finalMoveSpeed);
    57.  
    58.     }
    59.  
    60.     void LateUpdate()
    61.     {
    62.         UpdateCamera();
    63.     }
    64.  
    65.     void UpdateCamera()
    66.     {
    67.         Camera.main.transform.localPosition = new Vector3(0f, 0.75f, 0f);
    68.         Camera.main.transform.localEulerAngles = Vector3.left * verticalLookRotation;
    69.     }
    70. }
    Notice how I split the code into methods (functions) this makes for neater and more reusable code. It is good practice to do this.

    EDIT:
    The forums keeps screwing my code and deleting some empty lines to split up code, why is that?
     
  4. spencer_white

    spencer_white

    Joined:
    Nov 9, 2015
    Posts:
    37
    Thanks, it does look alot neater! But, sadly, it probably won't fix the original issue...I put my Camera controlling code in lateUpdate already, thinking that the camera would render everything after the player moved, and it would fix it...Sadly, it didn't fix the issue. I'm wondering at this point if it's one of Unity's classic unsolvable issues, like fast objects teleporting through things, etc.