Detect collision from a particular side

Detect collision from a particular side

I'm making a platform sidescrolling game. All I want to do is to detect if my character is on the floor:
function OnCollisionStay (col : Collision){
    if(col.gameObject.tag == "Floor"){
        onFloor = true;
    } else {onFloor = false;}
}
function OnCollisionExit (col : Collision){
    onFloor = false;
}

But I know this isn't the accurate way. If I hit a cube with a "floor" tag, in the air (no matter if with the character's feet or head) I would be able to jump.
Is there a way to use the same box collision to detect if I'm touching something from a specific side?

Solutions/Answers:

Answer 1:

You don’t have to have only one collider on your character; you can have multiple colliders to perform different checks!

I would suggest creating a separate collider that is located on your character’s feet. You could also have a collider for the top of your head, or maybe your front or back so you know when you bump into a wall…

Another way would be, when you collide with something, use Physics.Raycast or Physics.RaycastAll to check for points just below your feet, to see if you’re standing on ground or not.

If you really wanted to only use one collider, within your collision functions, you could check the col.contacts points to see if the collision occurred above or below the mid point of your collider.

Answer 2:

You can check the col.normal, well that’s how I do this. For example if the x value is 1, I know the collision is on the bottom of my collider. (that’s an example, I don’t recall the values of the normals)

Answer 3:

Note that if you’re using a Character Controller, you should use isGrounded to check for collisions with the ground:

From the docs:

Was the CharacterController touching the ground during the last move?

void Update() {
    CharacterController controller = GetComponent<CharacterController>();
    if (controller.isGrounded)
        print("We are grounded");
}

And it sounds like you should be, since it’s best suited for characters such as those you’d use in a platformer. The wording of the docs suggests this is precalculated during each Move operation, so you should look at this before adding extra colliders/triggers.

Answer 4:

Add this code to your player. Make a transform child object that is in the feet of the player. This code will determine weather the feet transform overlaps on ground.That means if player is grounded.

  public Transform theGround; //  A empty transform on the feet of the player.
  public LayerMask groundLayer; // Determines the ground.
  float groundRadius; //radius of the overlap circle to ground
  bool isGrounded;
    private void FixedUpdate()
    {
        isGrounded = false;
        Collider2D[] col = Physics2D.OverlapCircleAll(theGround.position, groundRadius, groundLayer);
        for (int i = 0; i < col.Length; i++)
        {
            if (col[i].gameObject != gameObject)
                isGrounded = true;
        }

    }

References