Best way to implement an advanced collision system?

Hi everyone,
we are working on a small space shooter-like game for android, which has multiple types of objects in a scene, all with its own behaviour when it comes to collision with another object.
For example, we have bullets that are destroyed when they touch anything, walls are never destroyed, but they do interact with other gameObject (physical and trigger), and enemies / player that can be hit multiple times before dying.

We don’t have problems understanding the basic collision system Unity has, so far we used all kinds of rigidbody and trigger colliders to achieve what we want, for instance we used trigger colliders on bullets, rigidbody physics colliders on enemies, and kinematic / static colliders on walls (obstacles).

The problem is, we want our gameObject to have different behavior depending on which object it collides. For example, we want to do nothing with the wall, when it is hit by a bullet, but we want to destroy an enemy when it is hit by a bullet. But also we dont want to destroy an enemy, when it hits another enemy. What we reeeeally want to avoid is this code (which i have seen many-many times in tuts and examples):

void OnTriggerEnter(Collider other) 
{
    if (other.tag == "Enemy")
    {
        //do something
    }
    if (other.tag == "Player")
    {
        //do something different
    }
}

In addition to comparing strings is the seedbed for errors, as our project grows bigger and bigger, collisions become totally out of control, even in this simple game. This way it is hard to tell why one object did (or did not) destroy another, and we have to look into 6-8 attached scripts to get a clue about what went wrong.
So far we used layer based colllision detection to limit interactions between objects, but its not enough since we want different things to happen even when objects are on the same layer…
…So we developed our own collision matrix, which tells what happens when two types of objects collide. This is very complex and very ineffective but readable.

The big question: what is the best way to implement a structure for our after-collision behaviour, that is more effective and readable than the above, less error prone, and it can be used in other projects as well? We dont fear interfaces, inheritence, or any type of structure (we use them in our project), we just cant figure out what’s the best way to implement this in Unity. Collisions are so basic in any game, i’m sure there are someone who went through all the trouble and can give us some ideas :slight_smile:

Thank you in advance!

Seems like some sort of lookup table of classes or delegates would work here… Here’s a pass at it…

Dictionary<ColliderObjectType, Dictionary<ColliderObjectType, ColliderHandler>> collisionMatrix;

// ColliderObjectType would be whatever key you need to lookup the type of object
// Collider handler is a delegate type or class type
// The outer dictionary is the collision source, the inner dictionary is what was collided with

// add a collision handler
void AddCollisonHandler(ColliderObjectType source, ColliderObjectType target, ColliderHandler handler)
{
    Dictionary<ColliderObjectType, ColliderHandler> handlers;
    if (!collisionMatrix.TryGetValue(source, out handlers)
    {
        // no handlers for source, so add it
        handlers = new Dictionary<ColliderObjectType, ColliderHandler>();
        collisionMatrix.Add(source, handlers);
    }

    // handlers is a reference to the handlers for this source, add the target
    // probably want to check for duplicates and such
    handlers.Add(target, handler);
}

// get a collision handler given source and target keys
bool TryGetHandler(ColliderObjectType source, ColliderObjectType target, out ColliderHandler handler)
{
    handler = null;

    Dictionary<ColliderObjectType, ColliderHandler> handlers;
    if (collisionMatrix.TryGetValue(source, out handlers)
    {
        if (handlers.TryGetValue(target, out handler))
        {
            return true;
        }
    }

    return false;
}

In Unity’s collision event you’d get the source and target keys and use them to get the handler…

 ColliderHandler handler;
 if (TryGetHandler(source, target, out handler)
 {
     handler(source, target, .... other stuff as needed ...);
     // or if it's a class...
     handler.HandleCollision(...);
 }
 else
 {
     // no collision handler for this combination - error, ignore, etc.
 }

This is effectively an implementation of your collision matrix, but makes it data driven instead of a bunch of hard coded logic. Depending on how you do the object keys (I was thinking types, but could just as easily be strings) you could even set this up in a config file, or the inspector or whatever.

…untested code, doubtless doesn’t handle various edge cases… other normal caveats…

I guess the key here is the lookup table concept. Add your various combinations to some sort of data structure that can ultimately give you a delegate or class that handles that particular combination.

Is this the best way? Can’t really say, but it’s what I’d do until I learn something better :slight_smile: