Search Unity

is grounded not working as intended (C#)

Discussion in 'Scripting' started by milliehashh, Feb 6, 2016.

  1. milliehashh

    milliehashh

    Joined:
    Sep 17, 2015
    Posts:
    72
    hey, ive recently been working with code where the is grounded feature is constantly ticking on and off, it cant determine when it is grounded :confused: this throws off the jumping mechanics sometimes too - ive been trying to get it working for a couple of days and ive tried a couple of different solutions but ive had no luck! im presuming it could be something to do with the gravity but im honestly not sure.
    i have the standard character controller applied to the character and this is the movement script


    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class movement : MonoBehaviour {
    5.  
    6.     public float moveSpeed = 6f;
    7.     public float jumpSpeed = 23f;
    8.     public float gravity = 60f;
    9.     public float airSpeed = 6f;
    10.     public bool grounded;
    11.  
    12.     public int jumps = 0;
    13.     public int maxJumps = 2;
    14.  
    15.     private CharacterController controller;
    16.  
    17.  
    18.     private Vector2 moveDirection = Vector2.zero; //initialize the move vector. Vector2 = 2 axes, Vector3 = 4 axes etc.
    19.  
    20.     // Use this for initialization
    21.     void Start () {
    22.         controller = GetComponent<CharacterController> ();
    23.     }
    24.  
    25.     void Jump()
    26.     {
    27.         moveDirection.y = jumpSpeed; //makes us move in the Y direction
    28.         jumps = jumps + 1;
    29.     }
    30.  
    31.     // Update is called once per frame
    32.     void Update ()
    33.     {
    34.         grounded = controller.isGrounded;
    35.  
    36.  
    37.  
    38.         if (controller.isGrounded) //if we're on the floor
    39.         {
    40.  
    41.             jumps = 0;
    42.  
    43.             moveDirection = new Vector2 (Input.GetAxisRaw ("Horizontal"), 0);
    44.             moveDirection = transform.TransformDirection (moveDirection);
    45.  
    46.             moveDirection *= moveSpeed;//we move direction * move speed
    47.  
    48.             if (Input.GetKeyDown(KeyCode.W))
    49.             {
    50.                 Jump ();
    51.             }
    52.  
    53.             controller.Move (moveDirection * Time.deltaTime);
    54.  
    55.         } else {
    56.  
    57.             //everything else is if we're in the air
    58.  
    59.             if (Input.GetKeyDown (KeyCode.W) && jumps < maxJumps) //jump
    60.             {
    61.                 Jump ();
    62.             }
    63.  
    64.  
    65.             moveDirection.y -= gravity * Time.deltaTime; //gravity
    66.  
    67.  
    68.             //lets you move in the air
    69.             moveDirection.x = Input.GetAxisRaw ("Horizontal") * airSpeed;
    70.             moveDirection = transform.TransformDirection (moveDirection);
    71.  
    72.             controller.Move (moveDirection * Time.deltaTime); //actually move
    73.  
    74.  
    75.         }
    76.     }
    77. }
    thanks for any help in advance, i just cant get my head around this
     
  2. Laperen

    Laperen

    Joined:
    Feb 1, 2016
    Posts:
    1,065
    This is an odd quirk of the unity character controller. You should add gravity all the time apparently. It doesn't have to be much, even using a magnitude of 1 while "grounded" is sufficient to mitigate this problem.
     
    nofreewill42 and milliehashh like this.
  3. milliehashh

    milliehashh

    Joined:
    Sep 17, 2015
    Posts:
    72
    Ah okay, how do I add that in, do I need a few lines of code or is it something that I can do within the controller? Thank you for the reply by the way!
     
  4. Suddoha

    Suddoha

    Joined:
    Nov 9, 2013
    Posts:
    2,824
    Try to apply it when you create the Vector2 with the horizontal axis. 0.1f or even less should be enough.
     
  5. Laperen

    Laperen

    Joined:
    Feb 1, 2016
    Posts:
    1,065
    The line which adds gravity to the character controller is already within your script. All you got to do is take it out of the if/else statement and make it independent, or called in either case. This is the line:
    Code (CSharp):
    1.             moveDirection.y -= gravity * Time.deltaTime; //gravity
     
  6. milliehashh

    milliehashh

    Joined:
    Sep 17, 2015
    Posts:
    72
    Thank you both, I'll give this a try and get back to you if it doesn't work - I'm pretty sure it will though :D
     
  7. milliehashh

    milliehashh

    Joined:
    Sep 17, 2015
    Posts:
    72
    hey, i tried to have it called in both cases and it didn't seem to work, not sure where id have to put it to make it independent, also tried applying it when the new vector was made and that didnt seem to work either, in all the different things i tried it either never picked up when the character was grounded (which caused my character to just keep rising when jump was pressed) or it just responded the same as before

    im fairly new to c# and this is the first time ive tried something like this so its most likely me making some newb mistake, i used a lot of different resources like tutorials to help me with this as well so ive probably mixed a few things up. if im doing something wrong or if you have any other ideas as to what can help let me know, thanks again for responding, i dont know what id do without these forums sometimes. :)
     
  8. Suddoha

    Suddoha

    Joined:
    Nov 9, 2013
    Posts:
    2,824
    What does your ground look like? It appears to be working for me just fine, couldn't find any flaws with the jumping mechanism either. Can you provide a bit more details?
     
  9. milliehashh

    milliehashh

    Joined:
    Sep 17, 2015
    Posts:
    72
    my ground is just a few sprites with box colliders on them, the majority of them are not straight though, a few of the beginning times are but the rest are at slight angles i think?



    again thanks for the help, i really appreciate this.
     
  10. milliehashh

    milliehashh

    Joined:
    Sep 17, 2015
    Posts:
    72
    Also how did you write the code to set the gravity to 0.1f? im not sure if im writing something out wrong as ive worked with javascript previously. If it would help ill probably be able to upload the project somewhere so you can take a further look, just let me know if thats the case. :)
     
    Last edited: Feb 7, 2016
  11. Suddoha

    Suddoha

    Joined:
    Nov 9, 2013
    Posts:
    2,824
    It wasn't necessary to add an extra small amount of gravity when I tested it, however, that was a 3D scene.

    It looks as if you use 3D physics aswell even though you might be better of with 2D in your case unless you need the 3D stuff. Unity offers quit simple tutorials to get you started, also 2D Character Controllers from scratch, e.g. this one.
     
  12. milliehashh

    milliehashh

    Joined:
    Sep 17, 2015
    Posts:
    72
    yeah i was waiting to see if that was gonna cause me any problems - so do you think thats whats giving me the issue then? i thought maybe sticking with regular colliders rather than 2D ones might have let me slip by that but clearly not. :confused: thanks, ill check the link out.
     
  13. Suddoha

    Suddoha

    Joined:
    Nov 9, 2013
    Posts:
    2,824
    I'm not saying it might cause troubles, it may cause troubles if you start to mix them up.
    I can really not tell that it is the cause of the problem that you're currently facing, but since you seem to work on a 2D project I'd really suggest to go the most appropriate way and use 2D physics as well.

    Anyway, as i accidently ignored your previous question about my suggestion:

    Your current line (which worked well in a scene for me without altering it)
    Code (CSharp):
    1. moveDirection = new Vector2 (Input.GetAxisRaw ("Horizontal"), 0);
    may be set to:
    Code (CSharp):
    1. moveDirection = new Vector2 (Input.GetAxisRaw ("Horizontal"), -0.1f);
    This will probably not change anything, but it's worth a try. It may force the CC to register another collision event for the upcoming frame instead of (for whatever reason) leaving it out.

    Also, make sure that, since you're using a CharacterController, you won't need another collider on the player object as this may also cause some problems when it's not set up properly.
     
    milliehashh likes this.
  14. milliehashh

    milliehashh

    Joined:
    Sep 17, 2015
    Posts:
    72
    Okay, ill bear that in mind for the future to stop any more problems like this, i tried to use all 3d colliders and such to sneak past problems but it didn't work out, at least i know for future reference i guess!

    No worries, that was what i tried when you first recommended that i change it and unfortunately it didn't work, thanks for responding anyways - other than my movement scripts and the character controller nothing else is applied, no colliders at all, thank you for letting me know though. :) if i ever do find some sort of solution to this ill respond here but at the moment, its looking unlikely.

    Thanks again for all the help, at least i expanded my knowledge on setting things up and using things correctly.
     
  15. Suddoha

    Suddoha

    Joined:
    Nov 9, 2013
    Posts:
    2,824
    If you want to I could have a look at it even though I usually don't do this. But it somehow bothers me that it's not fixed. :p
     
  16. Ironmax

    Ironmax

    Joined:
    May 12, 2015
    Posts:
    890
  17. Laperen

    Laperen

    Joined:
    Feb 1, 2016
    Posts:
    1,065
    While that is true, Raycast is not something that should be used on every frame for efficiency reasons. Fact remains the issue can be solved with a single line. The problem he/she faces now is lack of knowledge to apply what any of us here have been saying.
     
    Last edited: Feb 8, 2016
  18. Suddoha

    Suddoha

    Joined:
    Nov 9, 2013
    Posts:
    2,824
    Raycasts aren't that inefficient. Of course it may be solved simplier, but on a modern PC you can have tons of raycasts in a frame. ;)
     
    Laperen likes this.
  19. Laperen

    Laperen

    Joined:
    Feb 1, 2016
    Posts:
    1,065
    Truedat, was just considering if they were on stuff like a basic enemy which will be duplicated several times, even worse for casts per frame. The lag stacks and the framerate just plummets from my own personal experience.
     
  20. Suddoha

    Suddoha

    Joined:
    Nov 9, 2013
    Posts:
    2,824
    I guess you're still far away from limits then :D Empty scene with 50.000 raycasts per frame runs stable 66-68 FPS on my machine.
     
  21. Ironmax

    Ironmax

    Joined:
    May 12, 2015
    Posts:
    890
    you only use raycast (linecast) if your "falling". and where controller.isGrounded is not triggering Its very efficient
     
  22. Ironmax

    Ironmax

    Joined:
    May 12, 2015
    Posts:
    890
    This also gives you the opportunity to make a "hit the ground event". with animation or fx etc.controller.isGrounded Is just not good enough.
     
    Laperen likes this.
  23. milliehashh

    milliehashh

    Joined:
    Sep 17, 2015
    Posts:
    72
    Thanks ironmax, I'll look into using raycast instead of is grounded. :) sorry that you've all had to explain a lot to me and that I haven't understood some things, I'm still very new to C# and I'm still learning - hopefully I'll look back on this at one point and understand it all.
     
  24. Ironmax

    Ironmax

    Joined:
    May 12, 2015
    Posts:
    890
    Let me give you some working code also :) i just feel like being nice here

    Use this method when you know your in the "air" . The right foot is linked to a bone in this case, but can be any gameobject as reference.

    Code (CSharp):
    1.     void RayCastToGrund()
    2.     {
    3.         GroundDistance = Rayhit.distance;
    4.  
    5.         FeetOffGroundTime += 1*Time.deltaTime;  // The time falling, reset on hit.
    6.        
    7.         if (Physics.Raycast(RightFoot.transform.position, Vector3.down, out Rayhit) && Rayhit.transform.tag == "GroundTouch"
    8.             || Physics.Raycast(RightFoot.transform.position, Vector3.down, out Rayhit) && Rayhit.transform.tag == "MovingPlatform")
    9.         {
    10.             if (Rayhit.distance < 1.47f || ChrController.isGrounded)
    11.             {
    12.  
    13.                 // event that happens when you hit the ground
    14.                 // Can be Enumerator with yield return new waitforsecounds example.
    15.             }
    16.         }
    17.        
    18.     }
    hope it helps
     
    Last edited: Feb 8, 2016
  25. nofreewill42

    nofreewill42

    Joined:
    Feb 3, 2019
    Posts:
    5
    It seems to works. Thank you!
     
  26. zeropointblack

    zeropointblack

    Joined:
    Jun 8, 2020
    Posts:
    197
    lol no it doesnt. if "isGrounded" is off, then the force of gravity is already on all the time regardless. so whats the difference? fact is, Unity devs made something which simply doesnt work.
     
    BraveBushCamper and Arjun-Gupte like this.
  27. BraveBushCamper

    BraveBushCamper

    Joined:
    Dec 1, 2020
    Posts:
    1
    Yup. My gravity is always on. isGrounded isn't fixed.
    Code (CSharp):
    1. public class PlayerMovement : MonoBehaviour
    2. {
    3.     public CharacterController controller;
    4.     public float speed = 12f;
    5.     public float gravity = -9.81f;
    6.     public float jumpHeight = 5;
    7.     Vector3 move;
    8.  
    9.     private Vector3 verticalVelocity;
    10.     // Update is called once per frame
    11.     void Update()
    12.     {
    13.         move = Input.GetAxis("Horizontal") * transform.right + (Input.GetAxis("Vertical") * transform.forward); //getAxis returns either 1, 0, or -1 depending on if key is pressed (W = 1, S = -1 for vertical axis, horizontal is A and D. End Vector is something like 1,0,1 or -1, 0, 1.
    14.        
    15.         controller.Move(move * speed * Time.deltaTime);
    16.  
    17.         if (controller.isGrounded && verticalVelocity.y < 0f)
    18.         {
    19.             verticalVelocity.y = 0f;
    20.         }
    21.  
    22.         Debug.Log(controller.isGrounded);
    23.         if (Input.GetButtonDown("Jump") && controller.isGrounded)
    24.         {
    25.             verticalVelocity.y = 5;
    26.         }
    27.  
    28.         verticalVelocity.y += gravity * Time.deltaTime; //(gravity acceleration is -9.8m/s...soo use Time.deltaTime to make it per second not per Frame)
    29.  
    30.         controller.Move(verticalVelocity * Time.deltaTime);
    31.  
    32.     }
    33. }
    this is very similar to what they have on their documentation, and it doesnt work lmao.
     
  28. zeropointblack

    zeropointblack

    Joined:
    Jun 8, 2020
    Posts:
    197
    the only way to fix this is, well, basically dont use a character controller because rigid body is infinitely better and more simpler to move a character with root motion animations, etc. but regardless of method used, both (including character controller) need a separate ground check sphere under the character checking if the character interacted with a ground layer. that seems to be the only way, but it for sure works.
     
  29. IccID

    IccID

    Joined:
    Feb 22, 2018
    Posts:
    1
    murillom likes this.
  30. murillom

    murillom

    Joined:
    Sep 28, 2019
    Posts:
    1
  31. rogodoy

    rogodoy

    Joined:
    Jan 24, 2013
    Posts:
    21
    private bool IsGrounded()// if use in tilemap mode this will fix isgrounded checking collision
    {
    return Physics2D.Raycast(transform.position, -Vector2.up);
    // return Physics2D.OverlapCircle(groundCheck.position, 1f, groundLayer); //old

    }