Search Unity

  1. New Unity Live Help updates. Check them out here!

    Dismiss Notice

Jump only working half the time

Discussion in 'Scripting' started by Nave5, Mar 26, 2020.

  1. Nave5

    Nave5

    Joined:
    Jan 22, 2020
    Posts:
    4
    I have a jump script which uses the transform of an empty game object at the bottom of my player to do a Physics.CheckSphere checking for a ground layer mask then it will allow my player to jump however for some reason it only allows me to jump half the time very randomly. I don't believe it the CheckSphere is the problem because while debuggin I found the boolean it returns doesn't effect whether I can jump and it always returns true while I am on the ground. I can't figure out what is wrong if anyone has any ideas please let me know.
    Thanks
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class Playermovement : MonoBehaviour
    6. {
    7.  
    8.     public CharacterController controller;
    9.     public float speed = 12f;
    10.     public float jumpHeight = 3f;
    11.     public float sprintspeed = 20f;
    12.     public float defaultspeed = 12f;
    13.  
    14.  
    15.     Vector3 velocity;
    16.     public float gravity = -9.81f;
    17.  
    18.     public Transform groundCheck;
    19.     public float groundDistance = 5f;
    20.     public LayerMask groundMask;
    21.     bool isGrounded;
    22.  
    23.  
    24.     void FixedUpdate()
    25.     {
    26.         isGrounded = Physics.CheckSphere(groundCheck.position, groundDistance, groundMask);
    27.  
    28.         if (isGrounded)
    29.         {
    30.             velocity.y = -0.2f;
    31.         }
    32.  
    33.         Debug.Log(isGrounded);
    34.         if (Input.GetButton("Fire3"))
    35.         {
    36.             speed = sprintspeed;
    37.         }
    38.         else
    39.         {
    40.             speed = defaultspeed;
    41.         }
    42.         float x = Input.GetAxis("Horizontal");
    43.         float z = Input.GetAxis("Vertical");
    44.  
    45.         Vector3 move = transform.right * x + transform.forward * z;
    46.  
    47.         controller.Move(move * speed * Time.deltaTime);
    48.  
    49.        
    50.  
    51.         velocity.y += gravity * Time.deltaTime;
    52.         if (Input.GetButtonDown("Jump") && isGrounded)
    53.         {
    54.             velocity.y = Mathf.Sqrt(jumpHeight * -2f * gravity);
    55.         }
    56.         controller.Move(velocity * Time.deltaTime);
    57.     }
    58.  
     
  2. Nave5

    Nave5

    Joined:
    Jan 22, 2020
    Posts:
    4
    Also if anyone has any advice on making player controllers in general I would love to hear it this is my first attempt at making one using the CharacterController haven't tried any other methods.
     
  3. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    5,510
    The problem is using the
    Input.GetButtonDown() 
    (or
    Input.GetKeyDown()
    ) in the
    FixedUpdate()
    function.

    Instead, make an
     Update()
    function and check for the key going down there, and set a boolean.

    Over in
    FixedUpdate()
    , when you see that boolean true, act on it and clear it to false.

    This timing diagram explains why this is important. Note where input is gathered and where FixedUpdate goes vs Update.

    https://docs.unity3d.com/Manual/ExecutionOrder.html
     
    Joe-Censored likes this.
  4. Joe-Censored

    Joe-Censored

    Joined:
    Mar 26, 2013
    Posts:
    7,769
    The GetButtonDown and GetKeyDown methods are only true on the single frame the button or key was pressed, but FixedUpdate is frame independent, meaning there can be many frames or no frames between calls to FixedUpdate. If there are greater than 1 frames in between calls to FixedUpdate then you will miss any inputs on those frames.

    So it is usually a bad idea to check for input in FixedUpdate, though it isn't as bad a problem if you were just checking if a key or button were held down instead of just pressed, since being held down will be true for all the frames the key is held down (less likely to miss the input in FixedUpdate then).

    So do what @Kurt-Dekker suggests. Get input in Update, then act on that input in FixedUpdate.
     
unityunity