Is the CapsuleCast function broken?

Hi all,

I can’t get Physics.CapsuleCast to work correctly at all. My goal is to do a basic check to see if a vertically-oriented, non-rotating capsule collider (That represents a 2-dimensional game character) is touching the ground (Represented by a cube) for a jump check. Here’s the function I’m using, complete with my original code to perform this task which is commented out (But it did work faithfully).

The behavior I experience is that the function only returns true if the collider is floating about 0.5 units above the floor. If in contact with the floor, it returns false. If it is in the floor (for testing, I turned the collider off), then it returns false. If I move it further away from the floor than about half a unit, it returns false. If I adjust the radius that is passed into the function to account for the half unit disparity, it returns false. If I swap the two capsule points, it returns false.

In short, no matter which order I pass the two points, and no matter what radius I pass, and no matter how far I sweep the test, it only returns true if the collider is around 0.5 units away from the floor. It only seems to return true if the floor is on the very edge of the test! This makes no sense at all, and after reading documentation from other posters about this function, I’m led to believe that it’s been broken from some time and hasn’t been fixed for several versions of Unity.

I also checked the Physics settings in the editor, and it has a tolerance of 0.01.

Can anybody help? Am I using the wrong function here? Is the documentation inaccurate?

private bool isGrounded () {
	/*
	float realDistance = myGameObject.collider.bounds.extents.y + 0.1f;
	if (	Physics.Raycast(myGameObject.transform.position, -Vector3.up, realDistance)
		|| 	Physics.Raycast(new Vector3(myGameObject.transform.position.x + myGameObject.collider.bounds.extents.x, myGameObject.transform.position.y, myGameObject.transform.position.z), -Vector3.up, realDistance)
		|| 	Physics.Raycast(new Vector3(myGameObject.transform.position.x - myGameObject.collider.bounds.extents.x, myGameObject.transform.position.y, myGameObject.transform.position.z), -Vector3.up, realDistance)) {
		return true;
	}
	else {
		return false;
	}
	*/
	CapsuleCollider collider = myGameObject.GetComponent<CapsuleCollider>();
	Vector3 position = myGameObject.transform.position;
	Vector3 point1 = new Vector3(position.x, position.y - collider.height*0.5f+collider.radius, position.z);
	Vector3 point2 = new Vector3(position.x, position.y + collider.height*0.5f-collider.radius, position.z);

	//Debug.DrawLine (point1, point2, Color.red);
	if (Physics.CapsuleCast(point1, point2, collider.radius, Vector3.down, 0.1f)) {
		return true;	
	}
	else {
		return false;	
	}
}

The two points in a capsule cast do not include the radius. They are the top and bottom of just the cylinder part. That’s from memory, but also in the docs (which I did not read back then): “The capsule is defined by the two spheres with radius around point1 and point2”

So starting 0.5 units above the floor is actually scraping the ground (assuming a standard 0.5 radius.)

The other part is that *casts don’t hit things they start inside, and w/o realizing the radius went 0.5 lower, many of your casts probably started below ground. My guess is shooting it just as it skims the ground might be hitting a tiny bump, or just being a weird edge case (technically, if I scrape against something, I am hitting it, sort of.)

Fix would be not to add the radius – just 1/2 the height. If you look at Ex in the docs, they calculate p1 and p2 using half the height, no radius .