0
\$\begingroup\$

I am programmatically placing 4 large dots on my 2D scene which already has some objects on it. If the new dot overlaps an existing object I want to destroy the existing object. All the objects have 2Dcolliders and all are on the same layer ("Action").

Since I only do this once during the initial setup of the game I don't want to use collision detection events, instead it would seem that Collider2D.OverlapCollider would be the way to do this but I can't get it to work. The following code is called from Start() after all the objects have been placed, and thinking it might be something to do with the colliders not being active until the first frames, I also called it from a mouse click with the same result (no overlaps).

    void EraseOverlapDots()
    {
        GameObject[] largeDots = GameObject.FindGameObjectsWithTag("LargeDot");
        foreach(GameObject ldot in largeDots)
        {
            Debug.Log("Object:" + ldot.tag + "(" + ldot.transform.position + ")");

            Collider2D collider = ldot.gameObject.GetComponent<Collider2D>();
            ContactFilter2D contactFilter2D = new ContactFilter2D();
            contactFilter2D.SetLayerMask(ldot.layer);
            contactFilter2D.useLayerMask = true;

            List<Collider2D> collisions = new List<Collider2D>();
            int colCount = collider.OverlapCollider(contactFilter2D, collisions);
            int i = 0;
            foreach (Collider2D col2d in collisions)
            {
                i++;
                Debug.Log("HIT"+i+":" + col2d.tag + "(" + col2d.transform.position + ")");
            }
        }
    }

In an attempt to debug this I purposely put 4 small dots in exactly the same position as the large dots to ensure they overlap. When I run the game they are visibly exactly on top of each other but the result is always zero overlaps.

\$\endgroup\$
2
1
\$\begingroup\$

I'm answering my own question because I did get this working. The problem was with the layermask.

Change this line:

contactFilter2D.SetLayerMask(ldot.layer);

to either:

contactFilter2D.SetLayerMask(Physics2D.GetLayerCollisionMask(ldot.layer));

or:

contactFilter2D.SetLayerMask(LayerMask.GetMask("Action"));

Both seem to work with the second version being easier to understand and more flexible since you can specify multiple layers if needed such as:

contactFilter2D.SetLayerMask(LayerMask.GetMask("Action", "Default"));

This solution was inspired by a comment at the bottom of this Unity Forum post: https://forum.unity.com/threads/solved-collider2d-overlapcollider-returns-0-and-no-overlaps-are-found.642409/

I have not yet found any detailed explanation or tutorials on ContactFilter2D.

\$\endgroup\$
1
  • \$\begingroup\$ Usually I like to expose a public LayerMask variable in the Inspector, so I can just check-off the layers I want and see exactly which ones are selected. This will still work even if a layer name changes, whereas the "stringly typed" version will break if that happens. \$\endgroup\$ – DMGregory Jan 20 at 11:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.