Why does controller.isGrounded turn false when first pressing Play?

For 1 frame after pressing Play the default controller.isGrounded turns false. This makes my “Fall” animation play once which isn’t good.

I tried to set isGrounded to false in Start() which did nothing, and I have a simple grounded timer but that solve another issue and not this one. I adjusted Skin Width, changed Min Move Distance to 0, have default Step Offset (I don’t need to change that). I also tried to apply downward force on start with velocity.y but that didn’t help. I’m trying to stick with the default controller.isGrounded as well. Does anyone have any ideas on this?

I just tested this on a whole different project with no animations or anything else and it still happens:

public class PlayerMovement : MonoBehaviour
{
    public CharacterController controller; 
    public float walkSpeed = 4f;      
    public float sprintingSpeed = 6.5f; 
    public float gravity = -25f;   
    public Vector3 velocity;
    private bool isGrounded = true;

    void Update()
    {
        isGrounded = controller.isGrounded;

        if (isGrounded)
        {
            if (velocity.y < 0)
            {
                velocity.y = -2f;
            }

            float horizontal = Input.GetAxis("Horizontal");
            float vertical = Input.GetAxis("Vertical");

            Vector3 move = transform.right * horizontal + transform.forward * vertical;

            float speed = Input.GetKey(KeyCode.LeftShift) ? sprintingSpeed : walkSpeed;

            velocity.x = move.x * speed;
            velocity.z = move.z * speed;
        }

        velocity.y += gravity * Time.deltaTime;

        controller.Move(velocity * Time.deltaTime);
    }
}

you don’t have to do it in start. initialize the property the same way you do any of the others with
bool isGrounded = true;

a bool’s default value is false.

Read the specific working of CharacterController.isGrounded:

Was the CharacterController touching the ground during the last move?

So when the character controller has not yet been moved, isGrounded will be false.

You may want to start with your own isGrounded boolean to true.

Yeah I already set the bool to true when declaring it at the top but I still get that one false call at the start of runtime.

I dont know how big of an issue that 1 “false” check is. I could just try and force the falling animation to not play when the game is first started but that could be a bad bandaid fix, no clue

unfortunately this didnt work. i have no other code in the project

alright, i’m here to help. this will also future proof your project a bit so bear with me. when you set your animations, don’t just switch the instant you’re grounded. what if you fall down a small bump? the falling animation will play. what you should do instead is store a float of falling time, and add to it every frame with delta time when in the air, and return to 0 upon landing. if this variable goes over a threshold, then play the animation. otherwise, stay standing.
if you really want to get fancy, you can even blend animation states and you can use this value to do it, but that’s a matter of preference.

Thanks for the reply. Basically just a grounded timer right? i have one in my other project (its not the code I have in my post) and so if i’ve been grounded for 0.2 seconds, the fall animation will not play. so if i walk over small bumps or like down a staircase, the fall animation never plays and the isgrounded bool also remains true. It works decently when falling from great heights, you can’t really notice the player standing still despite falling since its very brief.

am I talking about something different here? my bad if so. also my grounded timer above doesn’t seem to fix the start issue with the 1 false check. I know the default controller.isGrounded check isn’t good but i’ve been trying to improve on it with multiple raycasts, etc.

yes, i am basically talking about a timer. if you implement it exactly as i described, there is no possible way that one frame from the character controller will play the animation. it’s all about gradual change.

if there are issues with it happening in one frame, it’s due to using the bool and not the float, or by setting the bool explicitly instead of only when the threshold was passed if you’re going that route.

I’m with POOKSHANK on making a dwell timer stuff like this… there are just too many ways for a transient single “not grounded” frame to get in there (edges between colliders, etc.) and cause mayhem.

I used it here:

Look for the groundedTimer in that snippet.

ALSO, if you’re just looking for a better FPS CC, here’s a cool one:

That one has run, walk, jump, slide, crouch… it’s crazy-nutty!!