Я бы просто сделал абстрактный метод для объекта Body с именем Collided:
abstract class Body
{
abstract void Collision(Body other);
}
class Dog : Body
{
public override void Collision(Body other) {
this.Bark();
}
public void Bark() { ... }
}
Тогда в вашей функции столкновения просто вызовите Collision для задействованных тел.
public bool OnCollision(Body body1, Body body2)
{
body2.Collision(body2);
}
Таким образом, любой тип тела может делать все, что ему нужно, когда происходит столкновение, вы даже можете оптимизировать это, чтобы отслеживать, какие тела были уведомлены о столкновениях друг с другом, и сократить количество вызовов функций, которые вы должны выполнить:
public bool OnCollision(Body body1, Body body2)
{
// Record that these two objects have been notified of a collision
// then when these same objects are the only two operands in subsequent calls
// you can just short circuit the calls.
if(!AlreadyNotifiedOfCollision(body1, body2))
{
body1.Collision(body2);
body2.Collision(body1);
NotifiedOfCollision(body1, body2);
}
}
Конечно, эмпирическое тестирование должно быть выполнено, чтобы подтвердить, что эта проверка быстрее, чем просто повторный вызов ...