【问题标题】:Check if UI elements/RectTransform are overlapping检查 UI 元素/RectTransform 是否重叠
【发布时间】:2017-02-04 16:58:32
【问题描述】:

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

目前我通过比较画布元素 Rects 来做到这一点

画布设置

  • 渲染模式:屏幕空间 - 相机
  • 像素完美:[是]
  • 渲染相机:主相机
  • 平面距离:100
  • 排序层:默认
  • 层内顺序:0

画布缩放器设置

  • UI 缩放模式:恒定像素大小
  • 比例因子:1
  • 每单位参考像素数:100

我用来检查的代码

[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。

矩形返回为(示例)

X -7.5,Y 2.5 W 98.5,H 164.1667

【问题讨论】:

    标签: c# user-interface unity3d rect


    【解决方案1】:

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

    【讨论】:

    • 这个脚本在我的测试中要好得多。它检测得很好。谢谢。
    • 这在锚点不在同一位置时不起作用,因为sizeDelta 将为零。
    【解决方案2】:

    将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 已经有rect 对象,使用它不是更便宜吗?
    • 这仅适用于两个对象具有相同父对象的情况。如果这不是保证,你会怎么做?
    • 我在屏幕坐标中看不到任何投影 - 您只是忽略了 z 坐标。这应该首先投影到屏幕坐标。
    猜你喜欢
    • 2021-06-08
    • 1970-01-01
    • 2017-04-25
    • 1970-01-01
    • 2012-08-17
    • 1970-01-01
    • 2016-06-07
    • 2011-06-15
    相关资源
    最近更新 更多