CharacterController.IsGrounded Not Working

using UnityEngine;

public class CharacterLocomotion : MonoBehaviour
{
    private CharacterController controller;

    private Animator animator;
    private Vector2 input;

    private float verticalVelocity;
    [SerializeField] private float stickToGroundForce = 10.0F;
    [SerializeField] private float jumpForce = 8.0F;
    [SerializeField] private bool isGrounded;

    void Start()
    {
        controller = GetComponent<CharacterController>();
        animator = GetComponent<Animator>();
    }

    void Update()
    {
        //Get Horizontal Inputs
        input.x = Input.GetAxis("Horizontal");
        input.y = Input.GetAxis("Vertical");
        //Animate The Character Based On Input
        animator.SetFloat("InputX", input.x);
        animator.SetFloat("InputY", input.y);

        isGrounded = controller.isGrounded;

        if (controller.isGrounded)
        {
            verticalVelocity = -stickToGroundForce * Time.deltaTime;
            if (Input.GetKeyDown(KeyCode.Space))
            {
                verticalVelocity = jumpForce;
            }
        }
        else
        {
            verticalVelocity -= stickToGroundForce * Time.deltaTime;
        }

        Vector3 moveVector = new Vector3(0, verticalVelocity, 0);
        controller.Move(moveVector * Time.deltaTime);
    }
}

controller.isGrounded is only calling true while I am moving and not standing still. I couldn’t find any other answers that seem to have worked online. Not only does it not work while I am standing still it also doesn’t work while walking down stairs or slopes where as walking up them works fine. Any help would be appreciated.

your code for determining if the player is grounded is in the controller script, which you’re referencing in this script, but aren’t actually showing, so there’s no way to determine whats wrong based off of what’s here.

The “controller” is a reference to the CharacterController component which is retrieved in the Start Function so it’s Unity Engine’s method of checking ground collision.

How are you actually moving your character? I only see code for jumping and animating.

The animation is what actually moves the character, I learned it from a very nice tutorial on YouTube and it’s actually very basic and reliable. Here it is in action, I warn you mute the video. My mic is buzzing like hell and I don’t know why lol.

https://www.youtube.com/watch?v=-EeSfI7UDk8

https://www.youtube.com/watch?v=_I8HsTfKep8

I’ve also fixed what I was trying to fix with help from taking some information from a Brackeys video. It now works as expected and I replaced the entire ground checking and jumping in my script with this.

#region Jumping And Ground Check

        //Phsyics Check To Ground
        isGrounded = Physics.CheckSphere(groundCheck.position, groundDistance, groundMask);

        //If The Player Is On The Ground Stick To Ground And Reset Vertical Velocity
        if (isGrounded && verticalVelocity < 0)
        {
            verticalVelocity = -stickToGroundForce;
        }

        //Jump If The Player Is Grounded
        if (isGrounded && Input.GetButtonDown("Jump"))
        {
            verticalVelocity += jumpForce * stickToGroundForce;
        }

        //Gravity
        verticalVelocity -= characterGravity * Time.deltaTime;

        //Apply These Calculations To The Actual Player Controller
        Vector3 fallVector = new Vector3(0, verticalVelocity, 0);
        controller.Move(fallVector * Time.deltaTime);

        #endregion
1 Like

I fixed this issue Setting Min Move Distance Character Controller value to 0. Now, controller.isGrounded works just as expected. I found it in a forum and it seems to work fine.

17 Likes

You have to push the charactercontroller to the ground with the gravity, and check the isgrounded after the “move” function.

9 Likes

For anyone doing custom gravity

// Always keep "pushing it" to maintain contact
if (collider.isGrounded)
    velocity_Gravity = gravity.normalized * 0.01f;
// Accelerate
else
    velocity_Gravity += gravity * Time.deltaTime * gravityMulti;

While we’re necroing old threads, do not use the Unity sample code for CharacterController.

I wrote about this before: the Unity example code in the API no longer jumps reliably.

I reported it in October 2020. Here is a work-around:

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.

1 Like

Code works fine if you switch the minimum distance detection in the character controller component from 0.001 to 0.

3 Likes

@MagyarPeter solution worked

Add constant -y movement to the controller and the detection works fine.

[SerializeField] float gravity = -4f;
 
moveDirection = new Vector3(
                            Input.GetAxis("Horizontal")* walkSpeed,
                            gravity,
                            Input.GetAxis("Vertical")* walkSpeed);
                                  
charController.Move(moveDirection * Time.deltaTime);

Debug.Log(charController.isGrounded);
1 Like

Adjust the skin width in character controller may be sometimes it will working for you. in my case i adjusted skin width 0.8 to 0.0001 it perfectly worked for me

5 Likes

This didn’t work for me, and I am using a gravity function to push the player down.

Same. I can zoom in on the collider after it drops and it’s actually sticking into the ground and still reports as “False.” If I just remove the conditional to check if it’s true, it will report true. Which I guess would be fine if I didn’t have conditions I needed to check, lol.

Guys just set Min Move Dis tance 0.001 to 0

6 Likes

work fine thanks

to be clear while setting the min move distance to 0 helps a lot, it still will fail to detect the ground when it’s probably just a couple centimeters below your feet. Is there a way to increase the distance threshold for counting as grounded without doing an additional collision detection?