Check if collision has ended

Hey,
I am trying to get the first part of my random dungeon generator to work and I am facing a few difficulties.

In general, it works like that:

  • a number of rooms that consist of a position, width and height, are created on random points in a circle and added to a list.

  • a GameObject with RigidBody2D and BoxCollider2D attached to it is instantiated for each room that has been created.

  • the physics-engine finishes the job by pushing the rooms apart.

The next step does not work as planned:
I have to wait until the GameObjects have been pushed apart which takes a few seconds and afterwards add the new positions of the rooms to my rooms-list.

The Problem is that I do not know how to detect when the process is finished.
(It is finished when no GameObject is colliding with another)
At the moment it creates the rooms during the pushing-process.

My first approach was to get the velocity of each object and add the new rooms when every velocity.magnitude is 0. Sadly, that did not work because the pushing via physics does not add any velocity to the them (I guess).

My second though was to solve this via OnCollisionExit() which is quite laborious because you have to add an extra script to each GameObject that returns a value if it does not collide. This way of solving the problem just does not sound right to me (but maybe it is).

Are there any other ways to get if my colliders are colliding or not?

private void splitRooms ()
    {
        // Create a GameObject foreach room in the list
        foreach (Room r in rooms)
        {
            GameObject g = new GameObject ("Room");
            g.AddComponent<BoxCollider2D> ();
            g.AddComponent<Rigidbody2D> ();

            Rigidbody2D rb = g.GetComponent<Rigidbody2D> ();
            rb.gravityScale = 0f;
            rb.freezeRotation = true;
            rb.mass = 1;
            rb.angularDrag = 0;
            rb.drag = 0;

            BoxCollider2D bc = g.GetComponent<BoxCollider2D> ();
            bc.size = new Vector2 (r.getIndexWidth (), r.getIndexheight ());
            bc.transform.position = r.getIndexPosition ();

            Instantiate (g, r.getIndexPosition (), Quaternion.identity, GameObject.Find ("Board").transform);
        }

        //  PROBLEM:  wait until the splitting-process is finished


        // Clear the list and add new rooms to it
        rooms.clear();
        foreach (Transform child in GameObject.Find("Board").transform)
        {
            BoxCollider2D bc = child.GetComponent<BoxCollider2D> ();
            int width = (int)bc.size.x;
            int height = (int)bc.size.y;

            generateRoom (child.transform.position, height, width);
        }
    }

Thank you for your help.

You might want to look into Unity - Scripting API: Collider2D.IsTouching or Unity - Scripting API: Collider2D.IsTouchingLayers

An other way that I assume should work…

using UnityEngine;

public class CollisionsDone : MonoBehaviour
{
    static public bool done = false;

    void Update()
    {
        if (done)
        {
            // all collisions should be done
        }
    }

    void LateUpdate()
    {
        done = true;
    }

    private void OnCollisionStay2D(Collision2D other)
    {
        done = false;
    }
}
1 Like

Thanks for your answer!

I tried to solve it with Collider2D.IsTouching but it doesn’t work.

bool done;
        do
        {
            done = true;

            foreach (Transform child in GameObject.Find ("Board").transform)
            {
                BoxCollider2D bc = child.GetComponent<BoxCollider2D> ();

                foreach (Transform child2 in GameObject.Find("Board").transform)
                    if (!child.Equals (child2))
                    {
                        BoxCollider2D bc2 = child.GetComponent<BoxCollider2D>();

                        if (bc.IsTouching (bc2))
                            done = false;
                    }
            }

        } while(!done);

Ok i guess the problem is that I call all my methods in Start() and the Collider-methods are getting called in the next frame in Update()