Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice

"IsGrounded" Always returns false for no apparent reason.

Discussion in 'Scripting' started by LucioHernandez, Apr 22, 2022.

  1. LucioHernandez

    LucioHernandez

    Joined:
    Apr 21, 2022
    Posts:
    10
    Hey, beginner coder here, I've got a question that seemed to be asked fairly often but I looked around for like 30 minutes and didn't find an answer, so I've got my player and everything works fine aside from the IsGrounded variable, I put it so it outputs onto the console and it always outputs as false, this makes it impossible for me to add gravity correctly or to add a jump mechanic, the most I managed to narrow it down to is IsGrounded just not detecting the ground, because it does stay directly under the player at all times, here's the code.

    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.  
    10.     public float speed = 12f;
    11.     public float gravity = -9.81f;
    12.     public float jumpHeight = 3f;
    13.  
    14.     public Transform groundCheck;
    15.     public float groundDistance = 0.4f;
    16.     public LayerMask groundMask;
    17.  
    18.     Vector3 velocity;
    19.     bool isGrounded;
    20.    
    21.     void Update()
    22.     {
    23.         isGrounded = Physics.CheckSphere(groundCheck.position, groundDistance, groundMask);
    24.  
    25.         if(isGrounded && velocity.y < 0)
    26.         {
    27.             velocity.y = -2f;
    28.         }
    29.  
    30.         float x = Input.GetAxis("Horizontal");
    31.         float z = Input.GetAxis("Vertical");
    32.  
    33.         Vector3 move = transform.right * x + transform.forward * z;
    34.  
    35.         controller.Move(move * speed * Time.deltaTime);
    36.  
    37.         velocity.y += gravity * Time.deltaTime;
    38.  
    39.         controller.Move(velocity * Time.deltaTime);
    40.  
    41.         Debug.Log(isGrounded);
    42.  
    43.     }
    44. }
    45.  
    And here's a small video of what happens:



    Any help is greatly appreciated.
     
  2. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    6,003
    LucioHernandez likes this.
  3. LucioHernandez

    LucioHernandez

    Joined:
    Apr 21, 2022
    Posts:
    10
    I tried the calling the controller.isGrounded script before, it didn't work, now I realize that I have a void Start(), thank you so much! It seems to be working fine now, really appreciate the help, definitely answered the questtion.
     
  4. LucioHernandez

    LucioHernandez

    Joined:
    Apr 21, 2022
    Posts:
    10
    I didn't have a void Start()*
     
  5. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    6,003
    That won't have affected anything. Monobehaviours can have any number Unity messages, including none.

    The way CharacterController.isGrounded works is that it checks if the capsule was intersecting with a collider the last time .Move() was called. To ensure this works reliably, you need a constant downward force pushing the the controller against the ground.
     
  6. LucioHernandez

    LucioHernandez

    Joined:
    Apr 21, 2022
    Posts:
    10
    Ok, then I must've screwed up somewhere else, isGrounded seems to work now, however another issue has come up, jump only works when I press forward, even if isGrounded = true, any issue as of why this could be happening, cause I've got zero clue, here's the code.
    Code (CSharp):
    1. public class PlayerMovement : MonoBehaviour
    2. {
    3.  
    4.     public CharacterController controller;
    5.  
    6.     public float speed = 12f;
    7.     public float gravity = -9.81f;
    8.     public float jumpHeight = 3f;
    9.  
    10.     public Transform groundCheck;
    11.     public float groundDistance = 5f;
    12.     public LayerMask groundMask;
    13.  
    14.     Vector3 velocity;
    15.     bool isGrounded;
    16.  
    17.     void Start()
    18.     {
    19.         controller = GetComponent<CharacterController>();
    20.     }
    21.  
    22.     void Update()
    23.     {
    24.         isGrounded = Physics.CheckSphere(groundCheck.position, groundDistance, groundMask);
    25.  
    26.         if(controller.isGrounded && velocity.y < 0)
    27.         {
    28.             velocity.y = -2f;
    29.         }
    30.  
    31.         float x = Input.GetAxis("Horizontal");
    32.         float z = Input.GetAxis("Vertical");
    33.  
    34.         Vector3 move = transform.right * x + transform.forward * z;
    35.  
    36.         controller.Move(move * speed * Time.deltaTime);
    37.  
    38.         if(Input.GetButton("Jump") && controller.isGrounded)
    39.         {
    40.             velocity.y = Mathf.Sqrt(jumpHeight * -2 * gravity);
    41.         }
    42.  
    43.         velocity.y += gravity * Time.deltaTime;
    44.  
    45.         controller.Move(velocity * Time.deltaTime);
    46.  
    47.         Debug.Log(controller.isGrounded);
    48.     }
    49. }
     
  7. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    6,003
    Taking a look, you're calling Controller.Move() twice in the same update loop. You should only be making one call to .Move() per loop as this is likely the cause of the unwanted behaviour. Additionally...

    CharacterController is a fancy form of rigid body, meaning it's evaluated in the same interval as FixedUpdate. When wanting to manipulate rigid bodies with inputs, you poll movements in Update and apply the values in FixedUpdate.

    In your case you can build a value for velocity in Update, and use that value in FixedUpdate in a single .Move() call. I would provide code examples though I'm not in front of an IDE and won't be for the next three days.
     
  8. LucioHernandez

    LucioHernandez

    Joined:
    Apr 21, 2022
    Posts:
    10
    Alright, I understand how calling more than one .Move() can definitely screw it up, but if I get rid of either one it either gets completely rid of gravity, or it gets rid of movement, I'll try to see what I can do to remove one, it most likely seemed like the issue.

    I've never used FixedUpdate() before, I'll have to look up how to use that, I do appreciate all the help you've been giving me, and while the code is still broken I understand more than I did before about a possible solution.
     
  9. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,947
    Definitely. And it's even worse because Unity's official documentation suggests doing so.

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

    I reported it to Unity via their docs feedback in October 2020. Apparently it is still broken:

    https://docs.unity3d.com/ScriptReference/CharacterController.Move.html

    Here is a work-around:

    https://forum.unity.com/threads/how...racter-movement-in-unity.981939/#post-6379746

    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.

    If you would prefer something more full-featured here is a super-basic starter prototype FPS based on Character Controller (BasicFPCC):

    https://forum.unity.com/threads/a-basic-first-person-character-controller-for-prototyping.1169491/

    That one has run, walk, jump, slide, crouch... it's crazy-nutty!!
     
  10. LucioHernandez

    LucioHernandez

    Joined:
    Apr 21, 2022
    Posts:
    10
    Yo! That's insane! I'll definitely have to check that out, right now I've moved onto another project, but I'll definitely revisit this when I have time, I really appreciate the help!
     
    Kurt-Dekker likes this.
  11. Banto

    Banto

    Joined:
    May 11, 2015
    Posts:
    1
    I've been running into the very same issue and they way I solved it for me was by locking the playerVelocity.y to a value o -1.0f when your grounded, before I used a value of -0.25f but this wasn't enough and simply pushing it to negative -1 solved it for now atleast. Hope it helps