Player not jumping while sprinting

Hello There,

I’m encountering an annoying problem that the player refuses to jump when I hit W + LShift then hit Space. I still have no clue if it was my script’s fault.

I will share the code here and hope for someone to figure it out. the code is a bit messy and unoptimized but I just getting started with the project. Here it is:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using TMPro;
using UnityEngine.InputSystem;

public class PlayerMovementTutorial : MonoBehaviour
{
    [Header("Movement")]
    public float moveSpeed;
 public GameObject playerobj;
    public float groundDrag;
    public Transform player;
    public float jumpForce;

    public float jumpCooldown;
    public float airMultiplier;
    public bool readyToJump;


    [Header("Ground Check")]
    public float playerHeight;
    public LayerMask whatIsGround;
   public bool grounded;

    float horizontalInput;
    float verticalInput;

    Vector3 moveDirection;

    Rigidbody rb;

    [Header("Animation")]
    public Animator an;

    private void Start()
    {
        rb = GetComponent<Rigidbody>();
        rb.freezeRotation = true;

        readyToJump = true;
    }

    private void Update()
    {
        // ground check
        grounded = Physics.Raycast(playerobj.transform.position, Vector3.down, playerHeight * 0.5f + 0.3f, whatIsGround);

       
        SpeedControl();

        // handle drag
        if (grounded)
           {
             rb.drag = groundDrag;
             an.SetFloat("Grounded",0);
           } 
        else
        {
            an.SetFloat("Grounded",1);
             rb.drag = 0;
        }

            if (Input.GetKey(KeyCode.Space))
    {
        Debug.Log("Entered");
        // Ensure the player is ready to jump and grounded
        if (grounded && an.GetBool("Run")==false)
        {
           
            
            
                 Debug.Log("Jump");
            // Trigger the jump animation
          
             an.SetBool("Jump",true);
            // Set a cooldown before the player can jump again
           
        }
        else if(grounded && an.GetBool("Run")==true)
        {
 an.SetBool("Walk",false);
                an.SetBool("Idle",false);
 Debug.Log("JumpRun");
            // Trigger the jump animation
          
        an.SetBool("JumpRun",true);
            // Set a cooldown before the player can jump again
         
         
        }
         readyToJump = false;
            Invoke(nameof(ResetJump), jumpCooldown);
    }
        

        
    }

    private void FixedUpdate()
    {
         MyInput();
        MovePlayer();
        MovementInputs();
    }

    private void MyInput()
    {
        horizontalInput = Input.GetAxisRaw("Horizontal");
        verticalInput = Input.GetAxisRaw("Vertical");

        // when to jump
        

    }

   private void MovePlayer()
{
    // Calculate movement direction relative to camera (improved)
    //moveDirection = orientation.forward.normalized * verticalInput + orientation.right.normalized * horizontalInput;
     moveDirection = player.forward.normalized * verticalInput + player.right.normalized * horizontalInput;
    // Movement on ground vs. air (unchanged)
    if (grounded)
    {
        rb.AddForce(moveDirection.normalized * moveSpeed * 10f, ForceMode.Force);
    }
    else
    {
        rb.AddForce(moveDirection.normalized * moveSpeed * 10f * airMultiplier, ForceMode.Force);
    }
}

    private void SpeedControl()
    {
        Vector3 flatVel = new Vector3(rb.velocity.x, 0f, rb.velocity.z);

        // limit velocity if needed
        if(flatVel.magnitude > moveSpeed)
        {
            Vector3 limitedVel = flatVel.normalized * moveSpeed;
            rb.velocity = new Vector3(limitedVel.x, rb.velocity.y, limitedVel.z);
        }
    }

    public void Jump()
    {
        // reset y velocity
        an.SetBool("Idle",false);
        rb.velocity = new Vector3(rb.velocity.x, 0f, rb.velocity.z);
        rb.AddForce(transform.up * jumpForce, ForceMode.Impulse);
        
    }
    private void ResetJump()
    {
                an.SetBool("Idle",true);

        readyToJump = true;
    }

    private void MovementInputs()
    {
        
        if(Input.GetKey(KeyCode.W))
            {
if(Input.GetKey(KeyCode.LeftShift))
         {
            Speed(5f);
            an.SetBool("Run",true);
              an.SetBool("Walk",false);
                 an.SetBool("Idle",false);
                 an.SetBool("LeftWalk",false);
                 an.SetBool("RightWalk",false);
                 an.SetBool("BackWalk",false);
                  an.SetBool("RightRun",false);
                 an.SetBool("BackRun",false);
                 an.SetBool("LeftRun",false);
    
                 
         }
         else if(Input.GetKey(KeyCode.LeftShift)==false)
         {
            Speed(2f);
               an.SetBool("Run",false);
              an.SetBool("Walk",true);
                 an.SetBool("Idle",false);
                 an.SetBool("LeftWalk",false);
                 an.SetBool("RightWalk",false);
                 an.SetBool("BackWalk",false);
                  an.SetBool("RightRun",false);
                 an.SetBool("BackRun",false);
                 an.SetBool("LeftRun",false);
         }
            }
            
            else if( Input.GetKey(KeyCode.A))
            {
                if(Input.GetKey(KeyCode.LeftShift))
                {
                    Speed(3f);
                  an.SetBool("Run",false);
                  an.SetBool("Walk",false);
                 an.SetBool("Idle",false);
                 an.SetBool("LeftWalk",false);
                 an.SetBool("RightWalk",false);
                 an.SetBool("BackWalk",false);
                  an.SetBool("RightRun",false);
                 an.SetBool("BackRun",false);
                 an.SetBool("LeftRun",true);
                }
                else
                {
                    Speed(1.5f);
                 an.SetBool("Run",false);
                 an.SetBool("Walk",false);
                 an.SetBool("Idle",false);
                 an.SetBool("LeftWalk",true);
                 an.SetBool("RightWalk",false);
                 an.SetBool("BackWalk",false);
                  an.SetBool("RightRun",false);
                 an.SetBool("BackRun",false);
                 an.SetBool("LeftRun",false);
                }
            }
             else if(Input.GetKey(KeyCode.D))
            {
                if(Input.GetKey(KeyCode.LeftShift))
                {
                    Speed(3f);
                  an.SetBool("Run",false);
                 an.SetBool("Idle",false);
                 an.SetBool("Walk",false);
                 an.SetBool("LeftWalk",false);
                 an.SetBool("RightWalk",false);
                 an.SetBool("BackWalk",false);
                  an.SetBool("RightRun",true);
                 an.SetBool("BackRun",false);
                 an.SetBool("LeftRun",false);
                }
                else
                {
                    Speed(1.5f);
                 an.SetBool("Run",false);
                 an.SetBool("Idle",false);
                 an.SetBool("Walk",false);
                 an.SetBool("LeftWalk",false);
                 an.SetBool("RightWalk",true);
                 an.SetBool("BackWalk",false);
                }
            }
            else if( Input.GetKey(KeyCode.S))
            {
                if(Input.GetKey(KeyCode.LeftShift))
                {
                 Speed(2.5f);
                  an.SetBool("Run",false);
                 an.SetBool("Idle",false);
                 an.SetBool("LeftWalk",false);
                 an.SetBool("RightWalk",false);
                 an.SetBool("BackWalk",false);
                  an.SetBool("RightRun",false);
                 an.SetBool("BackRun",true);
                 an.SetBool("LeftRun",false);
                }
                else
                {
                Speed(1.5f);
                 an.SetBool("Run",false);
                 an.SetBool("Idle",false);
                 an.SetBool("LeftWalk",false);
                 an.SetBool("RightWalk",false);
                 an.SetBool("BackWalk",true);
                }
            }
            else
            {

            Idle();

            }

             if(Input.GetKey(KeyCode.W) && Input.GetKey(KeyCode.A) || Input.GetKey(KeyCode.W) && Input.GetKey(KeyCode.D))
            {
               moveSpeed=0;
             Idle();
            }
            
            
    }

    private void Idle()
    {
  an.SetBool("Walk",false);   
               an.SetBool("Run",false);
               if(grounded)
             an.SetBool("Idle",true);  

            an.SetBool("LeftWalk",false);
            an.SetBool("RightWalk",false);
             an.SetBool("BackWalk",false);
              an.SetBool("LeftRun",false);
              an.SetBool("RightRun",false);
               an.SetBool("BackRun",false);
    }
    private void Speed(float speed)
    {
        moveSpeed=speed;
    }
}

I forgot to mention something. that actually the jumprun bool actually turns true sometimes. but only when I release LShift. for example
I’m sprinting with W + LShift
I have to release LShift and quickly press Space and then the JumpRun bool will actually turn true which is a messed up behaviour

Hope someone respond fast

FixedUpdate is not a valid place to make Input-Manager’s Input.Get___ calls -these belong to Update.

That being said, Input.GetAxis was not that affected by this much in your case but you would certainly notice it when using Input.GetKeyDown() or Input.GetButtonDown() here.

Oh no, wait:

Case solved I guess.

Solution:

Use Update for input readouts and rendering-related code.
Use FixedUpdate for gameplay logic and physics-related code.

@andrew-lukasik I have put MyInput() and MovementInputs() in Update() and changed Input.GetKey(KeyCode.Space) to Input.GetKeyDown(KeyCode.Space) and still nothing changed.
I forgot to mention something. that actually the jumprun bool actually turns true sometimes. but only when I release W and LShift. for example

I’m sprinting with W + LShift
I have to release them and quickly press Space and then the JumpRun bool will actually turn true which is a messed up behaviour

New note: It does do the job when I release the LShift only not W + LShift

This Invoke is cancelling jump, every frame:

@andrew-lukasik no, it isn’t. here is the modified one. but the problem still occurs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using TMPro;
using UnityEngine.InputSystem;

public class PlayerMovementTutorial : MonoBehaviour
{
    [Header("Movement")]
    public float moveSpeed;
 public GameObject playerobj;
    public float groundDrag;
    public Transform player;
    public float jumpForce;

    public float jumpCooldown;
    public float airMultiplier;
    public bool readyToJump;


    [Header("Ground Check")]
    public float playerHeight;
    public LayerMask whatIsGround;
   public bool grounded;
  public bool sprint;

    float horizontalInput;
    float verticalInput;

    Vector3 moveDirection;

    Rigidbody rb;

    [Header("Animation")]
    public Animator an;

    private void Start()
    {
        rb = GetComponent<Rigidbody>();
        rb.freezeRotation = true;

        readyToJump = true;
    }

    private void Update()
    {
        // ground check
        grounded = Physics.Raycast(playerobj.transform.position, Vector3.down, playerHeight * 0.5f + 0.3f, whatIsGround);

       
        SpeedControl();
         MyInput();
        MovementInputs();

        // handle drag
        if (grounded)
           {
             rb.drag = groundDrag;
             an.SetFloat("Grounded",0);
           } 
        else
        {
            an.SetFloat("Grounded",2);
             rb.drag = 0;
        }

        

        

    }

    private void FixedUpdate()
    {
        
        MovePlayer();
    }

    private void MyInput()
    {
        horizontalInput = Input.GetAxisRaw("Horizontal");
        verticalInput = Input.GetAxisRaw("Vertical");

        // when to jump
        
            if (Input.GetKeyDown(KeyCode.Space))
    {
        Debug.Log("Entered");
        // Ensure the player is ready to jump and grounded
        if (grounded && an.GetBool("Run")==false)
        {
           
            
            
                 Debug.Log("Jump");
            // Trigger the jump animation
                  readyToJump = false;

             an.SetBool("Jump",true);
             jumpCooldown=2.5f;
            // Set a cooldown before the player can jump again
           
        }
        else if(grounded && an.GetBool("Run")==true)
        {
            sprint=false;

 an.SetBool("Walk",false);
                an.SetBool("Idle",false);
 Debug.Log("JumpRun");
            // Trigger the jump animation
          
        an.SetBool("JumpRun",true);
        readyToJump = false;
            // Set a cooldown before the player can jump again
         
         
        }

        
         
            Invoke(nameof(ResetJump), jumpCooldown);
    }

    }

   private void MovePlayer()
{
    // Calculate movement direction relative to camera (improved)
    //moveDirection = orientation.forward.normalized * verticalInput + orientation.right.normalized * horizontalInput;
     moveDirection = player.forward.normalized * verticalInput + player.right.normalized * horizontalInput;
    // Movement on ground vs. air (unchanged)
    if (grounded)
    {
        rb.AddForce(moveDirection.normalized * moveSpeed * 10f, ForceMode.Force);
    }
    else
    {
        rb.AddForce(moveDirection.normalized * moveSpeed * 10f * airMultiplier, ForceMode.Force);
    }
}

    private void SpeedControl()
    {
        Vector3 flatVel = new Vector3(rb.velocity.x, 0f, rb.velocity.z);

        // limit velocity if needed
        if(flatVel.magnitude > moveSpeed)
        {
            Vector3 limitedVel = flatVel.normalized * moveSpeed;
            rb.velocity = new Vector3(limitedVel.x, rb.velocity.y, limitedVel.z);
        }
    }

    public void Jump()
    {
        // reset y velocity
        an.SetBool("Idle",false);
        rb.velocity = new Vector3(rb.velocity.x, 0f, rb.velocity.z);
        rb.AddForce(transform.up * jumpForce, ForceMode.Impulse);
        
    }
    private void ResetJump()
    {
                an.SetBool("Idle",true);

        readyToJump = true;
         jumpCooldown=3f;
    }

    private void MovementInputs()
    {
        
    if(Input.GetKey(KeyCode.W))
        {
            if(Input.GetKey(KeyCode.LeftShift))
         {
             sprint=true;
            Speed(5f);
            an.SetBool("Run",true);
              an.SetBool("Walk",false);
                 an.SetBool("Idle",false);
                 an.SetBool("LeftWalk",false);
                 an.SetBool("RightWalk",false);
                 an.SetBool("BackWalk",false);
                  an.SetBool("RightRun",false);
                 an.SetBool("BackRun",false);
                 an.SetBool("LeftRun",false);
    
                 
         }
         else if(Input.GetKey(KeyCode.LeftShift)==false)
         {
            sprint=false;
            Speed(2f);
               an.SetBool("Run",false);
              an.SetBool("Walk",true);
                 an.SetBool("Idle",false);
                 an.SetBool("LeftWalk",false);
                 an.SetBool("RightWalk",false);
                 an.SetBool("BackWalk",false);
                  an.SetBool("RightRun",false);
                 an.SetBool("BackRun",false);
                 an.SetBool("LeftRun",false);
         }
            }
            
            else if( Input.GetKey(KeyCode.A))
            {
                if(Input.GetKey(KeyCode.LeftShift))
                {
                    Speed(3f);
                  an.SetBool("Run",false);
                  an.SetBool("Walk",false);
                 an.SetBool("Idle",false);
                 an.SetBool("LeftWalk",false);
                 an.SetBool("RightWalk",false);
                 an.SetBool("BackWalk",false);
                  an.SetBool("RightRun",false);
                 an.SetBool("BackRun",false);
                 an.SetBool("LeftRun",true);
                }
                else
                {
                    Speed(1.5f);
                 an.SetBool("Run",false);
                 an.SetBool("Walk",false);
                 an.SetBool("Idle",false);
                 an.SetBool("LeftWalk",true);
                 an.SetBool("RightWalk",false);
                 an.SetBool("BackWalk",false);
                  an.SetBool("RightRun",false);
                 an.SetBool("BackRun",false);
                 an.SetBool("LeftRun",false);
                }
            }
             else if(Input.GetKey(KeyCode.D))
            {
                if(Input.GetKey(KeyCode.LeftShift))
                {
                    Speed(3f);
                  an.SetBool("Run",false);
                 an.SetBool("Idle",false);
                 an.SetBool("Walk",false);
                 an.SetBool("LeftWalk",false);
                 an.SetBool("RightWalk",false);
                 an.SetBool("BackWalk",false);
                  an.SetBool("RightRun",true);
                 an.SetBool("BackRun",false);
                 an.SetBool("LeftRun",false);
                }
                else
                {
                    Speed(1.5f);
                 an.SetBool("Run",false);
                 an.SetBool("Idle",false);
                 an.SetBool("Walk",false);
                 an.SetBool("LeftWalk",false);
                 an.SetBool("RightWalk",true);
                 an.SetBool("BackWalk",false);
                }
            }
            else if( Input.GetKey(KeyCode.S))
            {
                if(Input.GetKey(KeyCode.LeftShift))
                {
                 Speed(2.5f);
                  an.SetBool("Run",false);
                 an.SetBool("Idle",false);
                 an.SetBool("LeftWalk",false);
                 an.SetBool("RightWalk",false);
                 an.SetBool("BackWalk",false);
                  an.SetBool("RightRun",false);
                 an.SetBool("BackRun",true);
                 an.SetBool("LeftRun",false);
                }
                else
                {
                Speed(1.5f);
                 an.SetBool("Run",false);
                 an.SetBool("Idle",false);
                 an.SetBool("LeftWalk",false);
                 an.SetBool("RightWalk",false);
                 an.SetBool("BackWalk",true);
                 an.SetBool("BackRun",false);
                 an.SetBool("RightRun",false);
                 an.SetBool("LeftRun",false);
                }
            }
            else
            {

            Idle();

            }

             if(Input.GetKey(KeyCode.W) && Input.GetKey(KeyCode.A) || Input.GetKey(KeyCode.W) && Input.GetKey(KeyCode.D))
            {
               moveSpeed=0;
             Idle();
            }
            
            
    }

    private void Idle()
    {
        sprint=false;
  an.SetBool("Walk",false);   
               an.SetBool("Run",false);
               if(grounded)
             an.SetBool("Idle",true);  

            an.SetBool("LeftWalk",false);
            an.SetBool("RightWalk",false);
             an.SetBool("BackWalk",false);
              an.SetBool("LeftRun",false);
              an.SetBool("RightRun",false);
               an.SetBool("BackRun",false);
    }
    private void Speed(float speed)
    {
        if(an.GetFloat("Grounded")<1 && readyToJump==false)
        moveSpeed=0;
        else if (an.GetBool("Jump")==true)
        {
            moveSpeed=0;
        }
        else
        moveSpeed=speed;
    }
}

if anyone see that error might not be from the script and from something else. please respond fast

Still, let me insist - it is. Calling Invoke every frame results in this method being called ±every frame as well. Effect of jumpCooldown completely disappears once it’s first invoke takes place. Hiding Invoke behind a method call does not resolve this.

EDIT:

You were right. The way you tab this section made me believe otherwise.

Haven’t tested this, but this is what I had on my mind - logic and input separation:

using UnityEngine;
using UnityEngine.Serialization;

[RequireComponent( typeof(Rigidbody) )]
public class PlayerMovementTutorial : MonoBehaviour
{
    [Header("Movement")]
    [SerializeField][FormerlySerializedAs("moveSpeed")] float _moveSpeed;
    [SerializeField] Transform _groundcheckOrign;
    [SerializeField][FormerlySerializedAs("groundDrag")] float _groundDrag;
    [SerializeField][FormerlySerializedAs("player")] Transform _playerTransform;
    [SerializeField][FormerlySerializedAs("jumpForce")] float _jumpForce;

    [SerializeField][FormerlySerializedAs("jumpCooldown")] float _jumpCooldown;
    [SerializeField][FormerlySerializedAs("airMultiplier")] float _airMultiplier;
    bool _isReadyToJump;

    [Header("Ground Check")]
    [SerializeField][FormerlySerializedAs("playerHeight")] float _playerHeight;
    [SerializeField][FormerlySerializedAs("whatIsGround")] LayerMask _whatIsGround;

    float _horizontalInput, _verticalInput, _jumpResetTime;
    bool _sprintInput, _isGrounded, _isSprinting;
    Rigidbody _rigidbody;

    [Header("Animation")]
    [SerializeField][FormerlySerializedAs("an")] Animator _animator;

#if UNITY_EDITOR
    void OnDrawGizmos()
    {
        var text = new System.Text.StringBuilder("+");
        {
            text.Append($"\nH input: {_horizontalInput}");
            text.Append($"\nV input: {_verticalInput}");
            text.Append($"\nIs grounded: {_isGrounded}");
            text.Append($"\nIs sprinting: {_isSprinting}");
            
            text.Append($"\nReady to jump: {_isReadyToJump}");
            text.Append($"\nJump input: {_sprintInput}");
        }
        UnityEditor.Handles.Label(transform.position,text.ToString());
    }
#endif

    void Start()
    {
        _rigidbody = GetComponent<Rigidbody>();
        _rigidbody.freezeRotation = true;
        _isReadyToJump = true;
    }

    /// <summary>Input readouts & rendering.</summary>
    void Update()
    {
        _horizontalInput = Input.GetAxisRaw("Horizontal");
        _verticalInput = Input.GetAxisRaw("Vertical");
        _sprintInput = Input.GetKey(KeyCode.LeftShift);

        // when to jump
        if (Input.GetKeyDown(KeyCode.Space))
        {
            Debug.Log("Entered");
            // Ensure the player is ready to jump and grounded
            if (_isGrounded && _animator.GetBool("Run")==false)
            {
                Debug.Log("Jump");
                // Trigger the jump animation
                _animator.SetBool("Jump",true);
                _jumpCooldown = 2.5f;
            }
            else if(_isGrounded && _animator.GetBool("Run")==true)
            {
                _isSprinting = false;

                _animator.SetBool("Walk",false);
                _animator.SetBool("Idle",false);
                Debug.Log("JumpRun");
                // Trigger the jump animation
                _animator.SetBool("JumpRun",true);
            }

            // Set a cooldown before the player can jump again
            _jumpResetTime = Time.time + _jumpCooldown;
            _isReadyToJump = false;
            // Invoke(nameof(ResetJump), jumpCooldown);
        }

        // void ResetJump()
        if( !_isReadyToJump && Time.time>_jumpResetTime )
        {
            _animator.SetBool("Idle",true);
            _isReadyToJump = true;
            _jumpCooldown = 3f;
        }
    }

    /// <summary>Gameplay logic & physics.</summary>
    void FixedUpdate()
    {
        // ground check
        _isGrounded = Physics.Raycast(_groundcheckOrign.position, Vector3.down, out RaycastHit ground, _playerHeight * 0.5f + 0.3f, _whatIsGround);
       
        // SpeedControl();
        Vector3 flatVel = new Vector3(_rigidbody.velocity.x, 0f, _rigidbody.velocity.z);

        // limit velocity if needed
        if(flatVel.magnitude > _moveSpeed)
        {
            Vector3 limitedVel = flatVel.normalized * _moveSpeed;
            _rigidbody.velocity = new Vector3(limitedVel.x, _rigidbody.velocity.y, limitedVel.z);
        }

        // MovementInputs();
        bool W = _verticalInput>0;
        bool A = _horizontalInput<0;
        bool S = _verticalInput<0;
        bool D = _horizontalInput>0;

        _isSprinting = W && _sprintInput;

        _animator.SetBool("Run",_isSprinting);
        _animator.SetBool("Walk",W && !_sprintInput);
        if(W)
        {
            Speed(_sprintInput ? 5f : 2f);
            _animator.SetBool("Idle",false);
            _animator.SetBool("LeftWalk",false);
            _animator.SetBool("RightWalk",false);
            _animator.SetBool("BackWalk",false);
            _animator.SetBool("RightRun",false);
            _animator.SetBool("BackRun",false);
            _animator.SetBool("LeftRun",false);
        }
        else if(A)
        {
            Speed( _sprintInput ? 3f : 1.5f);
            _animator.SetBool("LeftWalk",!_sprintInput);
            _animator.SetBool("LeftRun",_sprintInput);
            _animator.SetBool("Idle",false);
            _animator.SetBool("RightWalk",false);
            _animator.SetBool("BackWalk",false);
            _animator.SetBool("RightRun",false);
            _animator.SetBool("BackRun",false);
        }
        else if(D)
        {
            Speed(_sprintInput ? 3f : 1.5f);
            _animator.SetBool("Idle",false);
            _animator.SetBool("LeftWalk",false);
            _animator.SetBool("BackWalk",false);
            _animator.SetBool("RightWalk",!_sprintInput);
            _animator.SetBool("RightRun",_sprintInput);
            _animator.SetBool("BackRun",!_sprintInput);
            _animator.SetBool("LeftRun",!_sprintInput);
        }
        else if(S)
        {
            Speed(_sprintInput ? 2.5f : 1.5f);
            _animator.SetBool("Idle",false);
            _animator.SetBool("LeftWalk",false);
            _animator.SetBool("RightWalk",false);
            _animator.SetBool("RightRun",false);
            _animator.SetBool("LeftRun",false);
            _animator.SetBool("BackWalk",!_sprintInput);
            _animator.SetBool("BackRun",_sprintInput);
        }
        else
        {
            _animator.SetBool("Idle",_isGrounded);
            _animator.SetBool("LeftWalk",false);
            _animator.SetBool("RightWalk",false);
            _animator.SetBool("BackWalk",false);
            _animator.SetBool("LeftRun",false);
            _animator.SetBool("RightRun",false);
            _animator.SetBool("BackRun",false);
        }

        // handle drag
        _rigidbody.drag = _isGrounded ? _groundDrag : 0;
        _animator.SetFloat("Grounded",_isGrounded ? 0 : 2);

        // MovePlayer();
        // Calculate movement direction relative to camera (improved)
        //moveDirection = orientation.forward.normalized * verticalInput + orientation.right.normalized * horizontalInput;
        Vector3 moveDirection = _playerTransform.forward * _verticalInput + _playerTransform.right * _horizontalInput;
        // Movement on ground vs. air (unchanged)
        float forceMultiplier = _isGrounded ? 1f : _airMultiplier;
        _rigidbody.AddForce( moveDirection.normalized * _moveSpeed * 10f * forceMultiplier, ForceMode.Force );
    }

    public void Jump()
    {
        // reset y velocity
        _animator.SetBool("Idle",false);
        _rigidbody.velocity = new Vector3(_rigidbody.velocity.x, 0f, _rigidbody.velocity.z);
        _rigidbody.AddForce(transform.up * _jumpForce, ForceMode.Impulse);
    }

    void Speed ( float speed )
    {
        if(_animator.GetFloat("Grounded")<1 && _isReadyToJump==false || _animator.GetBool("Jump")==true)
            _moveSpeed = 0;
        else
            _moveSpeed = speed;
    }
}

FSM

@yosfgaber I strongly recommend using FSM pattern when programming character controllers. It adds some preparation work but provides massive benefits for the readability and maintability of such code.

Here is an example of a scaffolding code for an inlined FSM:
Goal: to write the most simple yet most useful FSM that convinces Unity devs who still use bool fields to keep track of ai states to change their misguided ways for the better. · GitHub

And here is my refactor attempt in this vein, totally untested so likely wont even work, but should give you some idea how destination station would look like:

using UnityEngine;
using UnityEngine.Serialization;

[RequireComponent( typeof( Rigidbody ) )]
public class PlayerMovementTutorial : MonoBehaviour
{
    [Header( "Movement" )]
    [SerializeField][FormerlySerializedAs( "moveSpeed" )] float _moveSpeed;
    [SerializeField] Transform _groundcheckOrign;
    [SerializeField][FormerlySerializedAs( "groundDrag" )] float _groundDrag;
    [SerializeField][FormerlySerializedAs( "player" )] Transform _playerTransform;
    [SerializeField][FormerlySerializedAs( "jumpForce" )] float _jumpForce;

    [SerializeField][FormerlySerializedAs( "airMultiplier" )] float _airMultiplier;
    [SerializeField] Rigidbody _rigidbody;

    [Header( "Ground Check" )]
    [SerializeField][FormerlySerializedAs( "playerHeight" )] float _playerHeight;
    [SerializeField][FormerlySerializedAs( "whatIsGround" )] LayerMask _whatIsGround;


    float _horizontalInput, _verticalInput, _jumpInputTime;
    bool _sprintInput;

    [Header( "Animation" )]
    [SerializeField][FormerlySerializedAs( "an" )] Animator _animator;

    EState _state = EState.IDLE;
    float _stateChangeTime;

#if UNITY_EDITOR
    void OnDrawGizmos ()
    {
        if( Application.isPlaying ) UnityEditor.Handles.Label( transform.position , $"{_state}" );
    }
    void OnValidate ()
    {
        if( _rigidbody!=null ) _rigidbody.freezeRotation = true;
    }
#endif

    /// <summary>Input readouts & rendering.</summary>
    void Update ()
    {
        _horizontalInput = Input.GetAxisRaw( "Horizontal" );
        _verticalInput = Input.GetAxisRaw( "Vertical" );
        _sprintInput = Input.GetKey( KeyCode.LeftShift );
        if( Input.GetKeyDown( KeyCode.Space ) ) _jumpInputTime = Time.time;
    }

    /// <summary>Gameplay logic & physics.</summary>
    void FixedUpdate () => OnStateTick( _state , Time.time - _stateChangeTime );

    void MovePlayerRigidbody ( float forceMultiplier = 1 )
    {
        Vector3 moveDirection = _playerTransform.forward * _verticalInput + _playerTransform.right * _horizontalInput;// Calculate movement direction relative to camera (improved)
        _rigidbody.AddForce( moveDirection.normalized * _moveSpeed * 10f * forceMultiplier , ForceMode.Force );

        // limit velocity if needed
        Vector3 vel = _rigidbody.velocity;
        Vector3 flatVel = new Vector3( vel.x , 0f , vel.z );
        if( flatVel.magnitude > _moveSpeed )
        {
            Vector3 limitedVel = flatVel.normalized * _moveSpeed;
            _rigidbody.velocity = new Vector3( limitedVel.x , vel.y , limitedVel.z );
        }
    }

    public void Jump ()
    {
        if( _state==EState.WALKING ) ChangeState( EState.JUMPING_WHILE_WALKING );
        else if( _state==EState.RUNNING ) ChangeState( EState.JUMPING_WHILE_RUNNING );
    }

    bool IsGrounded ()
    {
        return Physics.Raycast( _groundcheckOrign.position , Vector3.down , out RaycastHit ground , _playerHeight * 0.5f + 0.3f , _whatIsGround );
    }

    /// <summary>Call this to change state.</summary>
    /// <remarks>Do not modify value _state outside this.</summaremarksry>
    void ChangeState ( EState nextState )
    {
        if( nextState == _state )
        {
            // do NOT comment this out, rethink the call logic to fix the damn warning
            Debug.LogError( $"{nameof( ChangeState )} fails as {nextState} is a current state already." );
            return;
        }

        OnStateExit( _state );
        _state = nextState;
        _stateChangeTime = Time.time;
        OnStateEnter( _state );
    }

    /// <summary>Good place to change animations, moving speed or play sounds etc.</summary>
    void OnStateEnter ( EState state )
    {
        // state starts:
        if( state == EState.IDLE )
        {
            _moveSpeed = 0;
            _rigidbody.drag = _groundDrag;
            _animator.SetBool( "Idle" , true );
            _animator.SetFloat( "Grounded" , 0 );
        }
        else if( state == EState.WALKING )
        {
            
        }
        else if( state == EState.RUNNING )
        {
            
        }
        else if( state == EState.JUMPING_WHILE_WALKING )
        {
            _moveSpeed = 0;
            _rigidbody.drag = 0;
            _rigidbody.velocity = new Vector3( _rigidbody.velocity.x , 0f , _rigidbody.velocity.z );// reset y velocity
            _rigidbody.AddForce( transform.up * _jumpForce , ForceMode.Impulse );
            _animator.SetBool( "Jump" , true );
            _animator.SetFloat( "Grounded" , 2 );

        }
        else if( state == EState.JUMPING_WHILE_RUNNING )
        {
            _moveSpeed = 0;
            _rigidbody.drag = 0;
            _rigidbody.velocity = new Vector3( _rigidbody.velocity.x , 0f , _rigidbody.velocity.z );// reset y velocity
            _rigidbody.AddForce( transform.up * _jumpForce , ForceMode.Impulse );
            _animator.SetBool( "JumpRun" , true );
            _animator.SetFloat( "Grounded" , 2 );
        }
        else if( state == EState.JUMPING_LANDING )
        {
            _moveSpeed = 0;
            _rigidbody.drag = 0;
        }
        else if( state == EState.FALLING )
        {
            _animator.SetBool( "Fall" , true );
            _animator.SetFloat( "Grounded" , 2 );
        }
        else throw new System.NotImplementedException( $"{state} not implemented" );
    }

    /// <summary>Good place to reset values</summary>
    void OnStateExit ( EState state )
    {
        // state ends:
        if( state == EState.IDLE )
        {
            _animator.SetBool( "Idle" , false );
        }
        else if( state == EState.WALKING )
        {
            _animator.SetBool( "Walk" , false );
            _animator.SetBool( "BackWalk" , false );
            _animator.SetBool( "LeftWalk" , false );
            _animator.SetBool( "RightWalk" , false );
        }
        else if( state == EState.RUNNING )
        {
            _animator.SetBool( "Run" , false );
            _animator.SetBool( "RightRun" , false );
            _animator.SetBool( "BackRun" , false );
            _animator.SetBool( "LeftRun" , false );
        }
        else if( state == EState.JUMPING_WHILE_WALKING )
        {
            _rigidbody.drag = _groundDrag;
            _animator.SetBool( "Jump" , false );
            _animator.SetFloat( "Grounded" , 0 );
        }
        else if( state == EState.JUMPING_WHILE_RUNNING )
        {
            _rigidbody.drag = _groundDrag;
            _animator.SetBool( "JumpRun" , false );
            _animator.SetFloat( "Grounded" , 0 );
        }
        else if( state == EState.JUMPING_LANDING )
        {
            _rigidbody.drag = _groundDrag;
        }
        else if( state == EState.FALLING )
        {
            _animator.SetBool( "Fall" , false );
            _animator.SetFloat( "Grounded" , 0 );
        }
        else throw new System.NotImplementedException( $"{state} not implemented" );
    }

    /// <summary>Good place to change states - always using ChangeState(_)!.</summary>
    void OnStateTick ( EState state , float duration )
    {
        float time = Time.time;
        bool W = _verticalInput>0;
        bool A = _horizontalInput<0;
        bool S = _verticalInput<0;
        bool D = _horizontalInput>0;

        // state update:
        if( state == EState.IDLE )
        {
            if( !IsGrounded() )
            {
                ChangeState( EState.FALLING );
                return;
            }

            if( W || A || S || D )
            {
                if( _sprintInput ) ChangeState( EState.RUNNING );
                else ChangeState( EState.WALKING );
                return;
            }
        }
        else if( state == EState.WALKING )
        {
            if( !IsGrounded() )
            {
                ChangeState( EState.FALLING );
                return;
            }

            if( _jumpInputTime+0.1f>time )
            {
                ChangeState( EState.JUMPING_WHILE_WALKING );
                return;
            }

            if( _sprintInput )
            {
                ChangeState( EState.RUNNING );
                return;
            }

            if( W )// WALK FORWARD
            {
                _moveSpeed = 2f;
                _animator.SetBool( "Walk" , true );
                _animator.SetBool( "BackWalk" , false );
                _animator.SetBool( "LeftWalk" , false );
                _animator.SetBool( "RightWalk" , false );
            }
            else if( S )// WALK BACKWARD
            {
                _moveSpeed = 1.5f;
                _animator.SetBool( "Walk" , false );
                _animator.SetBool( "BackWalk" , true );
                _animator.SetBool( "LeftWalk" , false );
                _animator.SetBool( "RightWalk" , false );
            }
            else if( D )// WALK RIGHT
            {
                _moveSpeed = 1.5f;
                _animator.SetBool( "Walk" , false );
                _animator.SetBool( "BackWalk" , false );
                _animator.SetBool( "LeftWalk" , false );
                _animator.SetBool( "RightWalk" , true );

            }
            else if( S )// WALK LEFT
            {
                _moveSpeed = 1.5f;
                _animator.SetBool( "Walk" , false );
                _animator.SetBool( "BackWalk" , false );
                _animator.SetBool( "LeftWalk" , true );
                _animator.SetBool( "RightWalk" , false );
            }
            else
            {
                ChangeState( EState.IDLE );
            }

            MovePlayerRigidbody();
        }
        else if( state == EState.RUNNING )
        {
            if( !IsGrounded() )
            {
                ChangeState( EState.FALLING );
                return;
            }

            if( _jumpInputTime+0.1f>time )
            {
                ChangeState( EState.JUMPING_WHILE_RUNNING );
                return;
            }

            if( _sprintInput==false )
            {
                ChangeState( EState.WALKING );
                return;
            }

            if( W )// RUN FORWARD
            {
                _moveSpeed = 5f;
                _animator.SetBool( "Run" , true );
                _animator.SetBool( "RightRun" , false );
                _animator.SetBool( "BackRun" , false );
                _animator.SetBool( "LeftRun" , false );
            }
            else if( A )// RUN LEFT
            {
                _moveSpeed = 3f;
                _animator.SetBool( "Run" , false );
                _animator.SetBool( "RightRun" , false );
                _animator.SetBool( "BackRun" , false );
                _animator.SetBool( "LeftRun" , true );
            }
            else if( D )// RUN RIGHT
            {
                _moveSpeed = 3f;
                _animator.SetBool( "Run" , false );
                _animator.SetBool( "RightRun" , true );
                _animator.SetBool( "BackRun" , false );
                _animator.SetBool( "LeftRun" , false );
            }
            else if( S )// RUN BACKWARD
            {
                _moveSpeed = 2.5f;
                _animator.SetBool( "Run" , false );
                _animator.SetBool( "RightRun" , false );
                _animator.SetBool( "BackRun" , true );
                _animator.SetBool( "LeftRun" , false );
            }

            MovePlayerRigidbody();
        }
        else if( state == EState.JUMPING_WHILE_WALKING )
        {
            float jumpCooldown = 2.5f;
            if( duration>jumpCooldown )
            {
                ChangeState( EState.JUMPING_LANDING );
                return;
            }

            MovePlayerRigidbody( _airMultiplier );
        }
        else if( state == EState.JUMPING_WHILE_RUNNING )
        {
            float jumpCooldown = 3f;
            if( duration>jumpCooldown )
            {
                ChangeState( EState.JUMPING_LANDING );
                return;
            }

            MovePlayerRigidbody( _airMultiplier );
        }
        else if( state == EState.JUMPING_LANDING )
        {
            if( W || A || S || D )
            {
                ChangeState( EState.WALKING );
                return;
            }

            if( duration>1f )// animation time limit
            {
                ChangeState( EState.IDLE );
                return;
            }
        }
        else if( state == EState.FALLING )
        {
            if( IsGrounded() )
            {
                ChangeState( EState.JUMPING_LANDING );
                return;
            }

            MovePlayerRigidbody( _airMultiplier );
        }
        else throw new System.NotImplementedException( $"{state} not implemented" );
    }

    public enum EState : byte
    {
        IDLE = 0,
        WALKING,
        RUNNING,
        JUMPING_WHILE_WALKING,
        JUMPING_WHILE_RUNNING,
        JUMPING_LANDING,
        FALLING,
    }

}

In my mind - it’s much better:

  • gets rid of overreliance on bool fields as a store of state (cheap to setup, costly to maintain)
  • removes logic code from appearing in totally unexpected places
  • moves logic to precise places where it belongs
  • Restricts communication with an Animator component to one-way messages only. This removes animator from a role of storing controller states… sometimes.