检查 UI elements/RectTransform 是否重叠

Check if UI elements/RectTransform are overlapping

我想知道如何检查我的 Unity Canvas 上的两个 UI 面板是否相互重叠。

目前我正在通过比较 canvas 元素 Rects

Canvas 设置

Canvas 缩放器设置

我用来检查的代码

[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);
}

会发生什么

'Overlapping' bool 立即变为 true。

Rect One returns 作为(示例)

X -7.5,Y 2.5 宽 98.5,高 164.1667

RectTransform 转换为 Rect 然后检查它是否重叠。

这是一个可以做到这一点的简单函数:

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);
}

用法:

public RectTransform uiRect1;
public RectTransform uiRect2;

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

更好的是,将其作为扩展方法:

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);
    }
}

现在,您可以

public RectTransform uiRect1;
public RectTransform uiRect2;

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

    }

    //OR

    if (uiRect2.rectOverlaps(uiRect1))
    {

    }
}

考虑到 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);
    }
}

这来自第一个答案(谢谢!),但我更新了它,因此无论枢轴在哪里,它都能正常工作。

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;
            Vector2 pivot = rectTransform.pivot;
            
            float rectTransformWidth = sizeDelta.x * rectTransform.lossyScale.x;
            float rectTransformHeight = sizeDelta.y * rectTransform.lossyScale.y;

            //With this it works even if the pivot is not at the center
            Vector3 position =rectTransform.TransformPoint(rectTransform.rect.center);
            float x = position.x - rectTransformWidth * 0.5f;
            float y = position.y - rectTransformHeight * 0.5f;
            
            return new Rect(x,y, rectTransformWidth, rectTransformHeight);
        }
    
}