Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

[2D] Best method for checking if player is grounded?

Discussion in 'Scripting' started by TumbaBit, Apr 11, 2014.

  1. TumbaBit

    TumbaBit

    Joined:
    Feb 17, 2013
    Posts:
    9
    First of all, I'm terribly sorry if this is in the wrong section, I didn't know if the 2D section was only for resources and such and not for scripting.

    I'm making a small platform with weird stuff like changing gravity and such, and I'm wondering what the best method for checking if a player is grounded, is. I know of the onCollisionEnter and the linecast method, but I was wondering if there was any other method better suited? A javascript snippet with a standard if/else that sets the grounded variable, would be greatly appreciated, whatever the best method is. Thank you very much.
     
  2. bara1247

    bara1247

    Joined:
    Oct 22, 2012
    Posts:
    40
    Hi
    Try this , i used it in many 2d games

    Code (csharp):
    1.  
    2.  
    3. public bool isGrounded ;
    4. public float slope = 60;
    5.  
    6. void FixedUpdate()
    7.  {
    8.     isGrounded = false;
    9.  }
    10.  
    11.  
    12. void OnCollisionStay(Collision cols)
    13.     {
    14.         foreach (ContactPoint contacts in cols.contacts)
    15.         {
    16.             if (Vector3.Angle(Vector3.up, contacts.normal) < slope)
    17.             {
    18.                 isGrounded = true;
    19.             }
    20.      }
    21.  
    22.  
     
  3. Ereous

    Ereous

    Joined:
    Aug 29, 2012
    Posts:
    163
    I used raycasts at my players feet.

    I'm omitting code obviously:

    Code (csharp):
    1.  
    2. void OnCollisionStay()
    3.     {
    4.         Vector3 myPos = _pgController.MyTrans.position;
    5.         Vector3 myScale = _pgController.MyTrans.localScale;
    6.         RaycastHit groundInfo;
    7.  
    8.         _isHittingObject = true;
    9.         //This is an additional check to see if we are "grounded" actually at the feet.. and not from the side.
    10.         if (Physics.Raycast(myPos + rightLeg, -_pgController.MyTrans.up, out groundInfo, myScale.y * checkDistance, ~(int)LayerEnums.Player) ||
    11.                 Physics.Raycast(myPos + leftLeg, -_pgController.MyTrans.up, out groundInfo, myScale.y * checkDistance, ~(int)LayerEnums.Player))
    12.         {
    13.             _pgController.IsGrounded = true;
    14.         }
    15.         else
    16.         {
    17.             _pgController.IsGrounded = false;
    18.         }
    19.     }
    20.  
    I use the _isHittingObject because I want to allow the player to continue to move while in the air. If you don't care about in air control don't worry about it. Otherwise you can just add in a simple check like this:

    Code (csharp):
    1.  
    2.  
    3. if (!_isHittingObject  !_pgController.IsGrounded || _isHittingObject  _pgController.IsGrounded)
    4.                     targetVelocity = new Vector3(1, 0, 1);
    5.  
    The difference between his and mine is I never set it back to false manually. His might be more efficient but its hard to know.
     
  4. TumbaBit

    TumbaBit

    Joined:
    Feb 17, 2013
    Posts:
    9


    Honestly, this doesn't seem very performance optimized. I might be wrong, but I would think this method took up way for resources than most other methods.
     
  5. TumbaBit

    TumbaBit

    Joined:
    Feb 17, 2013
    Posts:
    9
    Thanks for posting. Just curious, but why do you name your variables/functions with an underscore in front? I've never seen that before.
     
  6. Ereous

    Ereous

    Joined:
    Aug 29, 2012
    Posts:
    163
    Its just similar to the mSomeVariable people use. Just a way of indicating your using a private variable.