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
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

Setting up my 2D Character Colliders & Ground Check (The Right Way)

Discussion in '2D' started by Mojoz, Feb 11, 2016.

  1. Mojoz

    Mojoz

    Joined:
    Dec 4, 2015
    Posts:
    4
    Hi everyone,

    I'm new here, and I'm loving unity and the community so far. I've been looking around here and learning a lot from you all, however some concepts are just very confusing to me and trying to understand through other users code is making it even harder. I want to setup my character the 'right' way and not use code that I'm just going to have to completely scrap/redo later on down the line.

    As of now, my tiles use polygon colliders (through the map creator 'Tiled') and for the ground check I'm using the OverLapCircle method as follows:

    Code (CSharp):
    1. void FixedUpdate()
    2.   {
    3.   grounded = Physics2D.OverlapCircle(groundCheck.position, groundCheckRadius, whatIsGround);
    4.   }

    However, what happens is if I set the groundCheckRadius too low, the character believes he is not grounded on the edges. To solve this, I set the groundCheckRadius higher, but then you can jump forever up walls because the character believes he is grounded. Example here:



    I've read from other users that RayCast could be a way to solve this, but I just don't understand how to set them up. I attempted to use this code:

    Code (CSharp):
    1.     //your variables at top of script
    2.         const int maxReturnedIntersections = 1;
    3.         private RaycastHit2D[] hits = new RaycastHit2D[maxReturnedIntersections];
    4.             private int groundedR;
    5.             private int groundedM;
    6.             private int groundedL;
    7.             private bool isGrounded;
    8.    
    9.     //Then in Update(), or you can create a custom function for better organization, called like, CheckCollision() and call CheckCollision(); in your update. But anyway:
    10.     void Update()
    11.     {
    12.     //Check Collisions
    13.     //We use the NonAlloc version of Linecast, since we're calling it every frame and this version won't allocate memory each time, it doesn't even use 0.01ms of processing time for one of these.
    14.             groundedR = Physics2D.LinecastNonAlloc(gndChkR_s.position, gndChkR_e.position,hits,(1 << LayerMask.NameToLayer("Ground")) | (1 << LayerMask.NameToLayer("PassthroughPlatform")));
    15.             groundedM = Physics2D.LinecastNonAlloc(gndChkM_s.position, gndChkM_e.position,hits,(1 << LayerMask.NameToLayer("Ground")) | (1 << LayerMask.NameToLayer("PassthroughPlatform")));
    16.             groundedL = Physics2D.LinecastNonAlloc(gndChkL_s.position, gndChkL_e.position,hits,(1 << LayerMask.NameToLayer("Ground")) | (1 << LayerMask.NameToLayer("PassthroughPlatform")));
    17.    
    18.             if ((groundedL > 0) || (groundedM > 0) || (groundedR > 0))
    19.             {
    20.                 isGrounded = true;
    21.                 anim.SetBool ("Grounded", true);
    22.             }
    23.             else
    24.             {
    25.                 isGrounded = false;
    26.                 anim.SetBool ("Grounded", false);
    27.             }
    28.     }
    29.  
    However, I just couldn't get this method to work properly. I would be very grateful for any help and assistance in solving this issue.

    Thanks!
     
  2. geek_freek

    geek_freek

    Joined:
    Aug 26, 2014
    Posts:
    51
    Instead of LinecastNonAlloc try using RaycastNonAlloc and see if that helps.

    The layers Ground and PassthroughPlatform -> are they to be neglected or are those the only ones being checked ??
     
  3. Mojoz

    Mojoz

    Joined:
    Dec 4, 2015
    Posts:
    4
    Hi there, I'll give that a try. I'm not sure about your question, since this is not my code but code that I had found from another post. I only have the layer Ground assigned, which is to all my walls, ground and ceiling.
     
  4. geek_freek

    geek_freek

    Joined:
    Aug 26, 2014
    Posts:
    51
    Yes , which would certainly mean that ground layers and passthroughplatform layers are the only ones being checked . So did you try with RayCastNonAlloc ??
     
  5. Mojoz

    Mojoz

    Joined:
    Dec 4, 2015
    Posts:
    4

    Okay, I seem to have got the Raycast working, except now my groundcheck always returns true. So I can now jump forever wherever I am, I've probably done something simple and silly here? Code is as follows:
    Code (CSharp):
    1.     public class PlayerControl : MonoBehaviour {
    2.    
    3.         public float moveSpeed;
    4.         public float jumpHeight;
    5.         private float moveVelocity;
    6.         //public Transform groundCheck;
    7.         //public Transform groundCheck2;
    8.         //public float groundCheckRadius;
    9.         public LayerMask whatIsGround;
    10.         //private bool grounded;
    11.         private bool doubleJumped;
    12.         private Animator anim;
    13.         public Transform firePoint;
    14.         public GameObject ninjaStar;
    15.         public float knockback;
    16.         public float knockbackCount;
    17.         public float knockbackLength;
    18.         public bool knockFromRight;
    19.         public float shotDelay;
    20.         private float shotDelayCounter;
    21.         public bool onLadder;
    22.         public float climbSpeed;
    23.         private float climbVelocity;
    24.         private float gravityStore;
    25.         private Rigidbody2D myrigidbody2D;
    26.    
    27.         //your variables at top of script
    28.         const int maxReturnedIntersections = 1;
    29.         private RaycastHit2D[] hits = new RaycastHit2D[maxReturnedIntersections];
    30.         private int groundedR;
    31.         private int groundedM;
    32.         private int groundedL;
    33.         public bool grounded;
    34.    
    35.         public Transform gndChkR_s;
    36.         public Transform gndChkL_s;
    37.         public Transform gndChkM_s;
    38.    
    39.         public Transform gndChkR_e;
    40.         public Transform gndChkL_e;
    41.         public Transform gndChkM_e;
    42.    
    43.    
    44.    
    45.         // Use this for initialization
    46.         void Start () {
    47.             anim = GetComponent<Animator>();
    48.             myrigidbody2D = GetComponent<Rigidbody2D>();
    49.             gravityStore = myrigidbody2D.gravityScale;
    50.    
    51.      
    52.         }
    53.    
    54.         void FixedUpdate()
    55.         {
    56.             //grounded = Physics2D.OverlapCircle(groundCheck.position, groundCheckRadius, whatIsGround);
    57.             //grounded = Physics2D.OverlapArea(groundCheck.position, groundCheck2.position, whatIsGround)
    58.    
    59.             //Check Collisions
    60.             //We use the NonAlloc version of Linecast, since we're calling it every frame and this version won't allocate memory each time, it doesn't even use 0.01ms of processing time for one of these.
    61.             groundedR = Physics2D.RaycastNonAlloc(gndChkR_s.position, gndChkR_e.position, hits, (1 << LayerMask.NameToLayer("Ground")) | (1 << LayerMask.NameToLayer("PassthroughPlatform")));
    62.             groundedM = Physics2D.RaycastNonAlloc(gndChkM_s.position, gndChkM_e.position, hits, (1 << LayerMask.NameToLayer("Ground")) | (1 << LayerMask.NameToLayer("PassthroughPlatform")));
    63.             groundedL = Physics2D.RaycastNonAlloc(gndChkL_s.position, gndChkL_e.position, hits, (1 << LayerMask.NameToLayer("Ground")) | (1 << LayerMask.NameToLayer("PassthroughPlatform")));
    64.    
    65.             if ((groundedL > 0) || (groundedM > 0) || (groundedR > 0))
    66.             {
    67.                 grounded = true;
    68.                 anim.SetBool ("Grounded", true);
    69.                 doubleJumped = false;
    70.    
    71.             }
    72.             else
    73.             {
    74.                 grounded = false;
    75.                 anim.SetBool ("Grounded", false);
    76.             }
    77.  
     
  6. geek_freek

    geek_freek

    Joined:
    Aug 26, 2014
    Posts:
    51
    Try doing this:-
    Play with distance value(only decrease it but not 0) until you find the right spot.
    Code (CSharp):
    1.  
    2. float distance=3f;
    3. groundedR = Physics2D.RaycastNonAlloc(gndChkR_s.position, -Vector3.up, hits,distance, (1 << LayerMask.NameToLayer("Ground")) | (1 << LayerMask.NameToLayer("PassthroughPlatform")));
    4.  
    --------> (No distance applied)
    Normal Ray

    ---------------> (distance applied is just scaling the vector by that amount)
    Scaled Ray