You can call off certain collision events like Unity does, allowing components to exist independently but still work together. For my physics engine, I have all collision processing centralized so detecting when a collision just started or ended, or if there is collision at all is just a matter of a boolean check and calling off the corresponding events. I.e.:
CollisionPair[,] CollisionPairs;
void ProcessCollision (Body b1, Body b2)
{
CollisionPair colPair = CollisionPairs[b1.ID, b2.ID];
if (/*CollisionDetected*/)
{
if (!colPair.IsColliding)
{
b1.OnCollisionEnter (b2);
b2.OnCollisionEnter (b1);
}
colPair.IsColliding = true;
}
else {
if (colPair.IsColliding)
{
b1.OnCollisionExit (b2);
b2.OnCollisionExit (b1);
}
colPair.IsColliding = false;
}
}
Then to listen to these events:
void Start ()
{
GetComponent<Body>().OnCollisionEnter += HandleOnCollisionEnter;
}
void HandleOnCollisionEnter (Body body)
{
if (body.Tag == "Bullet")
{
Health -= 20;
}
}