Check object collision from script

Hello, im working with object event collisions via scripting and i’ve been struck with OnCollisionEnter/OnTriggerEnter/etc methods. I figured that you must attach a script to every object that has a collider that you want to handle events.
Lets say i have a game object that has a lot of childrens with colliders on it and i want to get collision events from each one, should i make a script for all of them? Is there any way to get all these collision events from one script attached to a random game object in the scene?
What i did is throw C# events on each collision, but i had to attach a LOT of scripts and its really upseting.

I think you will have to put a small script on each object ( But it will be the same script ):

C# :

and in parent class a function like ;

I didnt try it myself so tell me how it goes…

I was hoping to not have to do that. I think Unity should have some kind of Physics listener, so i can get all events or those which i want to listen from one script, just like box2d does.

What I did that worked really well when I needed to receive collision messages from child colliders, was create an interface called ICollisionListener (or something like that) that had all the collision methods defined in it, and a small monobehaviour component that I attached to the child colliders.

On Start, the monobehaviours would recursively search for any monobehaviour component on parent gameobjects that implemented this interface, and once found, they’d listen to the normal mb collision/trigger messages, and pass them on through the interface.

That ended up working very well, since it was easy to set up and could be applied to any number of child colliders in a big game object.

Note that this only applies for child colliders who also have rigidbodies of their own, if there are no rigidbodies inside the hierarchy, then IIRC the collision events do get passed upwards to the object with the rigidbody. This workaround was necessary in my case because we did have a complex game object which contained internal rigidbodies, so events wouldn’t reach the script they had to reach.

Cheers

If I understand your question correctly, you want to have something that checks for collisions, and you have a lot of colliders that you want to check for, yes?

This depends on what is colliding with what, but you don’t necessarily need to have a collision script on each object.
For example, if you had a player object, and then many objects that represnt pickups for the player, then you would only need one script on the player that checks for collision, checks to see what it collides with, and then do whatever logic with it you want. For example, on the player object:

void OnCollisionEnter (collision collided)
{
    if(collided.gameObject.tag == "theTagWeWant")
    //dostuff
}

You understand?
This of course assumes that you want to do the same thing to all objects with the tag “theTagWeWant” that collide with your player object.
You could also reverse the logic here and do stuff to the player, rather than the collided, for example reduce player’s health.

Now if your situation demands that different things happen depending on what object is collided with, then you will need to program individual behaviour for each situation. You can, however, still have just the one script on the player that checks for collisions and does different things depending on what it collided with. For example:

void OnCollisionEnter (collision collided)
{
    if(collided.gameObject.tag == "oneThing")
    //dostuff something

    else if(collided.gameObject.tag == "anotherThing")
    //do some other stuff

    else if //you get the idea
}

Is this what you were looking for?

No, because that way will allways check collisions between the object which you attached the script and any other in the world. What i need is a way to receive collision events generated between all colliders in the scene from a single script, so i could do something like this:

void CollisionBegin(Collider objA, Collider objB, Collision collision)
{
       if (objA.gameObject.tag == "My Tag A"  objB.gameObject.tag == "My Tag B")
       {
                // 2 desired objects in the scene collided, now i would do something with it
       }
}

Your example doesn’t make much sense. You want to check for a collision between two specific objects, but you don’t want Unity to check if a collision that has occured is between the two specific objects? What do you think Unity is going to do, be psychic and say “Oh I think these are the two objects the programmer wants” without actually checking if they are what you want?

I don’t think you understand how collisions work in Unity. Whenever two objects collide, Unity automatically fires off events, whether anything is listening for them or not. The way to listen to these events is to use the in-built functions OnCollisionEnter(collision), OnCollisionStay(collision) and OnCollisionExit(collision).
Notice that these functions accept only one parameter, which will be a collision object that the listening object had collided with. It doesn’t care what collides with what, it will fire it off on any collision. It is up to you to then check if this is the collision you want, and do something about it.

Why do you care if there will always be a check whether you have collided with your wanted object or not? Do you fear performance issues? Unless you are putting colliders and rigidbodies on thousands of objects all colliding with each other (for example an explosion), then there isn’t going to be any problems. BTW, don’t put colliders and rigidbodies on thousands of objects during an explosion.

If you are still adamant to only listen for an event that is fired off only when your two specific objects collide and ignore the ones provided by Unity, then please go ahead and implement a custom solution.

I dont think you are getting the idea. I have a empty game object in my scene where i attached a script named “Game”, which handles game logic in the scene. So it would be much less work if i would be able to listen some physics events than having to attach a script that raises collision events to every collider i want to handle in my scene.
This is just a simple example of what i think it could be really usefull:

void Start()
{
    // Start listening in this script all begin collision events generated by these 2 colliders
    Physics.ListenCollisionBegin(colliderA, colliderB);
    // Start listening in this script all begin collision events generated by game objects with those tag names
    Physics.ListenCollisionBegin("tag A", "tag B");
}

// Event raised by listening colliders/game object tags
void CollisionBeginEvent(Collider a, Collider b)
{
    // Handle all events generated by the objects i started to listen
}

Is there any approach to actually do this?

My apologies. I was having a particularly bad day at work yesterday and failed to keep my tone neutral in my previous reply. That is no excuse to communicate in the manner I did and so seek your pardon.

Unity is designed with OOP principles in mind, and in fact goes further with that and promotes component-based thinking, where objects are made up of individual components, and programming is split up into small, succinct “behavioural scripts”, as they like to call them.
Forgoing this design and keeping all of your game logic in one giant script is certainly possible, but will be going against the grain, so to speak.
You will face quite a few difficulties if you want to implement your programming in such a manner with Unity.

To do what you want will require you to come up with your own solution. First thing that comes to my mind would be to keep track of both object’s positions in world space and should they intersect then do whatever it is you want to do with them. I’m afraid I won’t be able to help more than that. Good luck!

I was hoping to not have to do that. I understand the idea of individual components, but im facing some problems which would be much more easier to fix if i would be able to do it like the example i did.

Super late with this, but you could always do something like:

public class SpecialCollisions : MonoBehaviour {
    public class TwoColliders
    {
        // define a class which just contains two game objects
        // because "SendMessage" can only take one parameter, so...
        GameObject collsion1;
        GameObject collision2;
        Public TwoColliders(GameObject collision1, GameObject collision2){
            this.collision1 = collision1;
            this.collision2 = collision2;
        }
    }
}

public class ColliderObject : MonoBehaviour {
    using SpecialCollisions;

    // this game object will send a message to "Game" script whenever it collides with anything
    // just attach this script to any object whose collisions you want to monitor
    public GameObject Game;

    void Start {
        Game = GameObject.Find("Game");
    }

    void OnCollisionEnter (Collision collision) {
        Game.SendMessage("GetCollision", new TwoColliders(gameObject, collision.gameObject));
    }
}


public class Game: MonoBehaviour {
    using SpecialCollisions;

    GameObject a, b;

    void Start(){
        // define some objects we're gonna care about later
        a = GameObject.Find("a")     
        b = GameObject.Find("b")     
    }

    void GetCollision (TwoColliders collision) {
        if (collision.collider1 == a && collision.collider2 == b){
            // those two objects from earlier have collided -- do something!
        }
    }
}