Forum rules - please read before posting.

How exactly does 'IsGrounded' work?

How exactly does 'IsGrounded' work?

I've got a 3D player, and I want to use it in the animator. Currently I've put it in the animator trough a script, which work fine.






        playerGrounded = KickStarter.player.IsGrounded();

        anim.SetBool ("IsGrounded", playerGrounded);  

But... Mid-air in the jump the bool suddenly turns on for 1 frame, then turns off again until the character hits the ground and then it stays off. Is this intentional? If so, what purpose does it serve? And if not, what could be wrong with my setup?

I'm having trouble getting my character to jump and fall correctly.
Is it possible to have a fall animation and temporarily turn root motion off? Or is that a bad solution?
«1

Comments

  • Without knowing what your setup is, it's hard to say.  If the Player has a Character Controller, that will be referred to - otherwise, it'll rely on its Capsule Collider.

    But jumping/falling in AC does assume that motion is due to the Rigidbody, and not root motion.  It may be that playing with the animation's import settings is enough to improve the motion without resorting to script.

    Bear in mind, however, that Mecanim characters have a Vertical movement float parameter field - this is the recommended way of playing falling animations.
  • edited September 2017
    Ok, I think I understand.

    I've got a Capsule Collider attached to the player and am using direct control on the player via the AC.Player script.

    Is the vertical float intented like this?
    • Grounded anim ---> Jumping anim [condition: Jump bool = true]
    • Jumping anim ---> Falling anim [condition: Vertical float < 0]
    • Falling anim ---> Grounded anim [condition: Vertical float > -0.1]
  • I'd say that's about right.  When it comes to having Animator parameters control your animations, it's more a case of what works for the user/character, but that's how it was intended at least.
  • Thanks Chris.

    It's good to know how it's intented before I put my own spin on it :)

    I've ditched the IsGrounded bool from the animator. I'm still using char.IsGrounded() in scripts for some dust particle effects while running and stuff. I get it now.

    A side-question though: Why is the Jump parameter for the animator a bool and not a trigger? (Not very important, but I'm just trying to understand the system)
  • Because it's set to False again only when the player becomes grounded again, making it easier to transition an idle -> jump -> land -> idle sequence.
  • Ohh, for some reason my Jump bool switches to false in mid-air. :/

    Any idea what could be wrong with my setup?
  • If it's being set to false, IsGrounded is being made true.

    Let's see the way your components are set up.  Screens of the Inspectors / Hierarchy and scene view would be great.
  • Last night I rebuild my player from scratch and the Jump bool is no longer switching off mid-air. I'm pretty sure I built it exactly the same, but probably not. Thanks though!

    I am however, doing things a bit hacked. In a script I turn root-motion off when the player isn't grounded and turn it back on when the player is grounded again.
    Hopefully this won't bring me into too much trouble. I just really like root-motion for walking/running/etc. It looks a lot better for my characters, I cannot get the same results without it.
  • Returning to this...

    Even without jumping, it seems that player.IsGrounded(); is returning false quite often when walking up and down slopes. The slopes aren't very steep.

    image
  • The grounded-check code occurs in Char.cs, line 3251.

    Try swapping around:

    if (_rigidbody != null && Mathf.Abs (_rigidbody.velocity.y) > 0.1f)
    {
      return false;
    }

    if (_collider != null && _collider.enabled)
    {
      return Physics.CheckCapsule (transform.position + new Vector3 (0f, _collider.bounds.size.y, 0f), transform.position + new Vector3 (0f, _collider.bounds.size.x / 4f, 0f), _collider.bounds.size.x / 2f);
    }


    so that it instead reads:

    if (_collider != null && _collider.enabled)
    {
      return Physics.CheckCapsule (transform.position + new Vector3 (0f, _collider.bounds.size.y, 0f), transform.position + new Vector3 (0f, _collider.bounds.size.x / 4f, 0f), _collider.bounds.size.x / 2f);
    }

    if (_rigidbody != null && Mathf.Abs (_rigidbody.velocity.y) > 0.1f)
    {
      return false;
    }


    Does that improve things?
  • Running up and down slopes works that way, but after swapping those pieces of code IsGrounded(); *always* returns True. Even when jumping or falling off ledges. That doesn't seem right, does it?

    (By the way, I am using IsGrounded for things like particles when running etc.)
  • Doesn't seem right at all.  But given the code change, that should only occur if it's detecting a collider.  It could be the Hotspot Detector - what layer is it on?  Try moving it to Ignore Raycast.
  • Ahhh, after a lot of testing and comparing with Tin Pot (on which isGrounded returned correctly) and completely stripping my player prefab to the core, I noticed the only difference left was that the actual Player-object itself was on a "Player" layer so I could exclude it from certain camera Culling Mask's.

    I've put that one back to Ignore Raycast and it's all good now.

    Thanks for all the help Chris! So happy this works now so I can focus on the content.

    Cheers!
  • How about the code change?  Does it work when reverted to the original, or is the change still necessary?
  • When I revert to the original the player can't walk up and down slopes properly.
    The new code works better for me!
  • Thanks, I'll consider an official change.
  • Cool.

    I also added a LayerMask to the CheckCapsule code. So the characters don't get grounded when they run into the water and start floating. But I understand code like that is a bit unnecessary for vanilla AC.

    Is there a good practice for overriding AC code? I'd rather not edit the AC scripts, because I don't want to break your system by accident. So I'm trying to have all my own scripts separated from AC, so I can keep AC up to date with the latest version at all times. Or should I just manually insert my own edits again after updating?
  • A character's entire movement code can be overridden (see this tutorial), but that's probably overkill for this.  Custom events are the recommended way to hook in custom code, but again that's not really right here.

    What's the specific code you're changing?  I'll consider adding it officially - but if not, it might be possible so simply make the function virtual so that a custom subclass can override it.
  • edited October 2017
    I've got an extra script CharExtras.cs on every player/NPC which does all kinds of things like managing different sounds and water things and jumping. It also contains two public LayerMasks called groundLayerMask and waterLayerMask which I know use like this. I check if a character is in the water in my own script.

    From Char.IsGrounded():





    if (_collider != null && _collider.enabled)
    {
    return Physics.CheckCapsule (transform.position + new Vector3 (0f, _collider.bounds.size.y, 0f), transform.position + new Vector3 (0f, _collider.bounds.size.x / 4f, 0f), _collider.bounds.size.x / 2f, GetComponent<CharExtras>().groundLayerMask);
    }


    if (_rigidbody != null && Mathf.Abs (_rigidbody.velocity.y) > 0.1f)
    {
            return false;
    }
  • edited October 2017
    A sidenote:

    I am making an adventure game that's not very heavy on action gameplay mechanics. It's mostly story and AC is a huge help even though It's not very point-and-clicky.

    I want the player to feel in control, I might end up building a custom movement code, but so far it doesn't seem necessary.
Sign In or Register to comment.

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Welcome to the official forum for Adventure Creator.