Check if UI elements/RectTransform are overlapping

15,304

Solution 1

Convert the RectTransform to Rect then check if it overlaps.

Here is a simple function that can do that:

bool rectOverlaps(RectTransform rectTrans1, RectTransform rectTrans2)
{
    Rect rect1 = new Rect(rectTrans1.localPosition.x, rectTrans1.localPosition.y, rectTrans1.rect.width, rectTrans1.rect.height);
    Rect rect2 = new Rect(rectTrans2.localPosition.x, rectTrans2.localPosition.y, rectTrans2.rect.width, rectTrans2.rect.height);

    return rect1.Overlaps(rect2);
}

Usage:

public RectTransform uiRect1;
public RectTransform uiRect2;

void Update()
{
    if (rectOverlaps(uiRect1, uiRect2))
    {
        Debug.Log("Overlaps");
    }else
    {
        Debug.Log("Does not Overlap");
    }
}

Even better, make it an extension method:

public static class ExtensionMethod
{
    public static bool rectOverlaps(this RectTransform rectTrans1, RectTransform rectTrans2)
    {
        Rect rect1 = new Rect(rectTrans1.localPosition.x, rectTrans1.localPosition.y, rectTrans1.rect.width, rectTrans1.rect.height);
        Rect rect2 = new Rect(rectTrans2.localPosition.x, rectTrans2.localPosition.y, rectTrans2.rect.width, rectTrans2.rect.height);

        return rect1.Overlaps(rect2);
    }
}

Now, you can do

public RectTransform uiRect1;
public RectTransform uiRect2;

void Update()
{
    if (uiRect1.rectOverlaps(uiRect2))
    {

    }

    //OR

    if (uiRect2.rectOverlaps(uiRect1))
    {

    }
}

Solution 2

Updated version considering scale of the rectTransform.

public static class RectTransformExtensions
{

    public static bool Overlaps(this RectTransform a, RectTransform b) {
        return a.WorldRect().Overlaps(b.WorldRect());
    }
    public static bool Overlaps(this RectTransform a, RectTransform b, bool allowInverse) {
        return a.WorldRect().Overlaps(b.WorldRect(), allowInverse);
    }

    public static Rect WorldRect(this RectTransform rectTransform) {
        Vector2 sizeDelta = rectTransform.sizeDelta;
        float rectTransformWidth = sizeDelta.x * rectTransform.lossyScale.x;
        float rectTransformHeight = sizeDelta.y * rectTransform.lossyScale.y;

        Vector3 position = rectTransform.position;
        return new Rect(position.x - rectTransformWidth / 2f, position.y - rectTransformHeight / 2f, rectTransformWidth, rectTransformHeight);
    }
}
Share:
15,304
Jim
Author by

Jim

Updated on June 09, 2022

Comments

  • Jim
    Jim almost 2 years

    I'd like to know how I check whether two UI Panels on my Unity Canvas are overlapping each other.

    Currently I am doing this by comparing the canvas elements Rects

    Canvas Settings

    • Render Mode: Screen Space - Camera
    • Pixel Perfect: [Yes]
    • Render Camera: Main Camera
    • Plane Distance: 100
    • Sorting Layer: Default
    • Order In Layer: 0

    Canvas Scaler Settings

    • UI Scale Mode: Constant Pixel Size
    • Scale Factor: 1
    • Reference Pixels Per Unit: 100

    Code I am using to check

    [Header("Check For Overlap")]
    public RectTransform PlayerBar;
    public RectTransform LeftBar;
    public Rect RectOne;
    public Rect RectTwo;
    public bool overlapping;
    
    //Check if the two canvas element Rects overlap each other
    
    public void CheckForOverlap()
    {
        overlapping = false;
        // Convert Canvas RectTransforms to World Rects
        RectOne = GetWorldRect(LeftBar);
        RectTwo = GetWorldRect(PlayerBar);
    
        if (RectOne.Overlaps(RectTwo))
        {
            overlapping = true;
        }
    }
    
    
    public Rect GetWorldRect(RectTransform rt)
    {
        //  Get World corners, take top left
        Vector3[] corners = new Vector3[4];
        rt.GetWorldCorners(corners);
        Vector3 topLeft = corners[0];
    
        // Rect Size ... I'm not sure if this is working correctly?
        Vector2 size = new Vector2(rt.rect.size.x, rt.rect.size.y);
        return new Rect(topLeft, size);
    }
    

    What happens

    'Overlapping' bool instantly changes to true.

    The Rect One returns as (example)

    X -7.5, Y 2.5 W 98.5, H 164.1667

  • Jim
    Jim about 7 years
    Thanks a lot, this was really useful. Especially the added tip for an extension method
  • Brackets
    Brackets about 5 years
    RectTransform already has rect object, wouldn't using it be less memory expensive?
  • WreckFish
    WreckFish over 3 years
    This only works if both objects have the same parent. How would you do this if this is not a guarantee?
  • oneiros
    oneiros over 3 years
    I don't see any projection in screen coordinates - you are only ignoring the z coordinate. This should projected first to screen coordinates.
  • krehwell
    krehwell over 3 years
    this script is so much better in my testing. it detects very well. thank you.
  • PNarimani
    PNarimani over 3 years
    This doesn't work when anchors are not in the same position because sizeDelta will be zero.