tags:

views:

249

answers:

4

The following event can possibly get called hundreds of times a frame.

public bool OnCollision(Body body1, Body body2)
{
 if(body2.Tag is Dog)
      ((Dog)body2.Tag).Bark();
}

I understand that using "is" causes a cast to be made and then when i want to do something with it, cast it a second time. Is there a more efficient way to check the type? I made a console app trying "if(body2.Tag.GetType() == typeOf(Dog))" but it appears to be even slower than using "is".

Thanks.

+14  A: 
 if(body2.Tag is Dog)

is actually compiled as

Dog Temp = body2.Tag as Dog;
if (temp != null)

In your code, you're then doing the cast again. Better would be:

Dog dog = body2.Tag as Dog;
if (dog != null)
{
    dog.Bark();
}
James Curran
Thanks I did not realize that! This is very helpful.
+6  A: 

I would just make an abstract method on the Body object called Collided:

abstract class Body
{
   abstract void Collision(Body other);
}

class Dog : Body
{
   public override void Collision(Body other) {
      this.Bark();
   }

   public void Bark() { ... }
}

Then in your collision function just call Collision on the involved bodies.

public bool OnCollision(Body body1, Body body2)
{
   body2.Collision(body2);
}

This way any type of body can do whatever it needs when a collision happens, you could even optimize this to keep track of which bodies have been notified of collisions with eachother and reduce the number of function calls that you have to execute:

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);
   }
}

Of course empirical testing would have to be done to validate that this check is faster than actually just doing the call twice...

joshperry
Well, that may be, but people like to upvote and accept answers that provide actual samples to solve their problem than just a 3 word answer and a link to wikipedia.
joshperry
Actually this isn't exactly double dispatch, my solution does not vary by the type that is passed into the Collision method of the Body.
joshperry
+1 I prefer your way to do it. Can't tell if it's faster but it's more elegant.
Daok
+1  A: 

Would an approach like this be feasible or useful?

public interface ICollidable
{
    void OnCollision();
}

public abstract class Body : ICollidable
{
    public abstract void OnCollision();
}

public class Dog : Body
{
    public override void OnCollision();
    {
        Bark();
    }
}

public Boolean OnCollision(ICollidable a, ICollidable b)
{
    b.OnCollision();
}
Anthony Mastrean
A: 

How about a generic collision method? Then there is no need for inheritance. Just an interface.

public bool OnCollision<TA,TB>(TA a, TB b)
    where TA : ICollidable
    where TB : ICollidable {
    a.Collision(b);
}
anonymous