characterController.isGrounded is false when I move backward?

I’m new to Unity here. My script allows my player to walk, sprint, crouch, and jump. At present, it has a very strange problem:
When my character moves forward, left, and right, characterController.isGrounded is True, but when it moves backward, characterController.isGrounded becomes False. This prevents my character from jumping while moving backwards.
This problem is bugging me and I can’t find similar problems and solutions. I guess there may be a mechanism problem with characterController, or the order of some statements in my code is incorrect?

using UnityEngine;
using UnityEngine.InputSystem;

public class PlayerController : MonoBehaviour
{
    private Animator animator;
    public Transform mainCamera;
    private CharacterController characterController;

    [Header("Move")]
        public float crouchSpeed = 1f;
        public float walkSpeed = 2f;
        public float sprintSpeed = 5f;
        public float rotationSpeed =5f;
        public float moveSpeed;
        private Vector3 moveDirection;
        private bool isCrouch = false;
    [Header("Jump")]
        public float jumpHeight = 2f;
        public float gravity = -10.0f;
        private Vector3 playerVelocity;
        private bool onGround;

    private void Start()
    {
        characterController = GetComponent<CharacterController>();
        animator = GetComponent<Animator>();
        moveSpeed = 0;
    }

    private void Update(){
        // Move
        moveDirection = mainCamera.right * Input.GetAxisRaw("Horizontal") + mainCamera.forward * Input.GetAxisRaw("Vertical");
        if(moveDirection == Vector3.zero){
            moveSpeed = 0;
            animator.SetFloat("moveSpeed",moveSpeed);
        }else if(isCrouch == true){
            moveSpeed = crouchSpeed;
            animator.SetFloat("moveSpeed",moveSpeed);
        }else if(Input.GetKey(KeyCode.LeftShift)){
            moveSpeed = sprintSpeed;
            animator.SetFloat("moveSpeed",moveSpeed);
            //animator.SetBool("isCrouch",false);
        }else{
            moveSpeed = walkSpeed;
            animator.SetFloat("moveSpeed",moveSpeed);
        }
       
        // Rotate
        if(moveDirection != Vector3.zero){
            Vector3 lookDirection = moveDirection;
            lookDirection.y = 0;
            var targetRotation = Quaternion.LookRotation(lookDirection);
            transform.rotation = Quaternion.Slerp(transform.rotation,targetRotation,rotationSpeed * Time.deltaTime);
        }
         // Jump
        onGround = characterController.isGrounded;
        Debug.Log(onGround);
        if (Input.GetButtonDown("Jump") && onGround){
            if(isCrouch == true){
                isCrouch = !isCrouch;
                moveSpeed = walkSpeed;
                animator.SetBool("isCrouch",isCrouch);
            }else{
                playerVelocity.y = Mathf.Sqrt(jumpHeight * -2f * gravity);
                animator.SetBool("isJump", true);
                Debug.Log("Jump");
            }
        }
        if (onGround && playerVelocity.y <= 0){
            playerVelocity.y = 0f;
            animator.SetBool("isJump", false);
        }
        playerVelocity.y += gravity * Time.deltaTime;
        characterController.Move(playerVelocity * Time.deltaTime + moveDirection * Time.deltaTime * moveSpeed);
    }
    // Crouch
    public void OnCrouch(InputValue inputValue){
        if (onGround){
            isCrouch = !isCrouch;
            if(isCrouch == true){
                moveSpeed = crouchSpeed;
                animator.SetBool("isCrouch",isCrouch);
            }
            else{
            moveSpeed = walkSpeed;
            animator.SetBool("isCrouch",isCrouch);
        }
        }
       
    }
}

By the way, I also discovered a problem with my code, LOL, that is, the height of my jump when walking is different from the height of my jump when sprinting, the latter is obviously lower. However, I only set one jump height, the same strange problem

You’re pushing the character along its local forward axis which means that if you have a mouse look script and you’re looking downwards towards the ground while pressing the back key then your character will lift off the ground slightly resulting in it no longer being able to jump. To prevent this you can flatten the moveDirection like so:

// Move
moveDirection = (mainCamera.right * Input.GetAxisRaw("Horizontal") + mainCamera.forward * Input.GetAxisRaw("Vertical")).normalized;
moveDirection.y=0; // flatten the direction to prevent any upwards force which could cause us to lift off the ground slightly. Warning - character will now be slightly slower when looking up or down
moveDirection=moveDirection.normalized; // normalize if you prefer a constant velocity regardless of looking up and down

Your rotation is a little unusual. Gamers typically want their character to strafe when using the A and D keys, but your character script also rotates. Although because of the way you’ve implemented the rotation code it will probably fail when pushing the back key. You can rotate with just this:

        // Rotate
        transform.Rotate(0,Input.GetAxisRaw("Horizontal") * 70 * Time.deltaTime,0);

BTW - You’re using both the old and new input systems which is a little unusual.

1 Like

Wow, your first code solved both of my problems at the same time. Now isGrounded has been corrected to true when walking backwards, and the height of the jump when sprinting is also the same as when walking! Awesome, thank you very much for your advice.
Also, my plan for the rotation is that when aiming (right mouse button), the character will always face where the crosshair is aimed, and when not aiming (right now), the character will face the direction he is walking. If I had a car or a tank as my character, your second code would work perfectly!
Also, I use both the old and new input systems LOL, and I didn’t even notice this problem myself. Thank you for bringing it up!