Detecting isGrounded with Rigidbody and Collider

On my player, I have decided to eschew the heavy character controller for a rigidbody and collider. In the past, I have used the the character controller and collision flags returned from the move method of the controller to determine whether the player is grounded, like this:

this.moveCollisions = this.charControl.Move(this.moveDir * Time.deltaTime);
this.isGrounded = (this.moveCollisions & CollisionFlags.CollidedBelow) != 0;

Now that I am using a rigidbody and collider only, my solution for detecting whether the player is grounded is being done like this:

(from the player controller script)

public function OnCollisionEnter(collisionInfo : Collision) {
  var anyGrounded: boolean;
  anyGrounded = false;
  for (var contact : ContactPoint in collisionInfo.contacts) {
	if (Mathf.Approximately(contact.normal.y, 1)) {
	  anyGrounded = true;
	}
  }
  if (anyGrounded) {
    this.isGrounded = true;
  }
  // Do other collision processing....
  return;
}

public function OnCollisionExit(collisionInfo : Collision) {
  var anyGrounded: boolean;
  anyGrounded = false;
  for (var contact : ContactPoint in collisionInfo.contacts) {
    if (Mathf.Approximately(contact.normal.y, 1)) {
      anyGrounded = true;
    }
  }
  if (anyGrounded) {
    this.isGrounded = false;
  }
  // Do other collision processing....
  return;
}

This seems to work well, but I am curious if there are unforeseen issues with the approach, and also if there is a better way.

2 Answers

2

I don’t think you’ll run into any issues like that. I’m a lot lazier then you are. When I have this issue I normally just shoot a ray out of -transform.up and then monitor it’s strike range etc.

This also gives me info like how far the character is from the ground if I want to calculate fall damage or anything.

But then again I don’t think there is anything wrong with using the collision system for this!

Thanks for your help. I thought about a ray cast solution a bit as well.

After further research, darthbator’s approach works better. The collider approach is somewhat unreliable.

Here’s the new approach (in FixedUpdate):

if (Physics.Raycast (this.transform.position, -Vector3.up, this.groundHit)) {
    if (this.groundHit.distance < 0.05) {
    	this.isGrounded = true;
    }
    else {
    	this.isGrounded = false;
    }
}