检查 UI 元素/RectTransform 是不是重叠
Posted
技术标签:
【中文标题】检查 UI 元素/RectTransform 是不是重叠【英文标题】: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
【问题讨论】:
【参考方案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 坐标。这应该首先投影到屏幕坐标。以上是关于检查 UI 元素/RectTransform 是不是重叠的主要内容,如果未能解决你的问题,请参考以下文章