I am creating a 2D platformer using Unity3D, I want to have the player destroy enemies when it jumps/falls over them (just from the top). But I have been having problems trying to implement this. I stripped everything and used two simple box colliders in order to make it easy. So, when onCollisionEnter2D
is called I get the bounds of the objects colliding like this:
Bounds playerBounds = new Bounds(transform.position, collider2D.bounds);
Bounds collisionBounds = new Bounds(collision.transform.position, collision.collider.bounds);
Then I check if the object colliding is below by comparing it's bounds:
//If the player's lowest point is greater than the
//colliding object's highest, then it is above it
bool isAbove = playerBounds.min.y >= collisionBounds.max.y;
Then I check if the object is actually an enemy, and if so, I destroy it:
if(isAbove)
{
if(collision.gameObject.tag == "Enemy")
{
collsion.gameObject.getComponent<EnemyController>().die();
}
}
Now the thing is this never happens, isAbove
is never true, so I tried checking the heights of each object so I use
Debug.Log("player : " + playerBounds.min.y + " enemy : " + collisionBounds.max.y)
It says the player bottom-most is below the enemy top-most. Since I use this same method to detect if the player is grounded in order to enable jumping I noticed it works beautifully with other things like platforms but not with enemies. Also y used Debug.break
to stop the game and noticed that when colliding with platforms the player's collider was always above the platform's, but when it collided with enemies they overlap: so the player's bottom-most part is below the enemy's top-most part. I read somewhere that this is due to the minPenetrationPenalty
property, I didn't like the results of messing with it so I just left it the same (If I lower it doesn't even work with platforms, and I increase it they don't even touch and the collision is detected). I tried to compensate for this penetration when checking the bounds so I said:
bool isAbove = playerBounds.min.y >= collisionBounds.max.y - 0.01;
It sometimes fails and sometimes not depending on the angle and other stuff, I still don't get it because if this was the problem It shouldn't work with the platforms either but it does, it only fails with enemy. I even tried to check for the overlap and said:
float overlap = playerBounds.min.y - collisionBounds.max.y;
bool isAbove = overlap > -0.01;
this still works beautifully with platforms only reporting positive values (which means they are not overlapping), but with enemies it actually reports negative values (which confirms the previous: they do overlap), even more strange it actually reports overlaps greater than what should be allowed, the usually report a -0.09
which means a 0.09 overlap which is greater than the 0.01 that the physics engine is supposed to allow.
If I apply this code in OnCollisionStay2D
instead it works, I guess by this time the overlap is fixed, but this looks unnatural and I still don't understand why this works perfectly with platforms (they never even overlap!) and not my enemies.
playerBounds.min.y >= collisionBounds.max.y*0.8f
\$\endgroup\$