RectTransform详解
示意图

1) anchor区域(浅绿色方框区域)
上图中parent的大小为300*200,所以anchorMin的距离为(60, 20) ,anchorMax的距离为(90, 20)
2) 节点坐标: 是相对anchor区域的
Vector2 offsetMin;
节点左下角相对anchor区域左下角的坐标
Vector2 offsetMax;
节点右上角相对anchor区域右上角的坐标
上面的图中:
offsetMin=(40, 30)
offsetMax=(-10, -30)
3) Vector2 sizeDelta;
节点自身大小与anchor区域大小的差值(即上图的白色区域减绿色方框区域),计算公式: sizeDelta=rectTransform.rect.size - anchorAreaSize=offsetMax-offsetMin
上面的图中:
sizeDelta=(-10, -30) - (40, 30)=(-50, -60)
4) Vector2 anchoredPosition;
表示自己的pivot相对parent的虚拟pivot的坐标

虚拟pivot的计算:
Vector2 virtualPivot = new Vector2(
Mathf.Lerp(anchorMin.x, anchorMax.x, pivot.x),
Mathf.Lerp(anchorMin.y, anchorMax.y, pivot.y)
);
a) 计算公式1:anchoredPosition = localPosition - parentRtf.rect.size × ( virtualPivot - (0.5, 0.5) )
上图中的virtualPivot = new Vector2(
Mathf.Lerp(0.2, 0.7, 0.4),
Mathf.Lerp(0.1, 0.9, 0.5)
) = (0.2 + 0.5*0.4, 0.1 + 0.8*0.5) = (0.4, 0.5), 即anchorArea的(40%宽度, 50%高度)
anchoredPosition = (-10, 0) - (300, 200) × ( (0.4, 0.5) - (0.5, 0.5) ) = (-10, 0) - (300, 200) × (-0.1, 0) = (20, 0)
b) 计算公式2: anchoredPosition = offsetMin + sizeDelta * pivot
上面的图中: anchoredPosition = (40, 30) + (-50, -60) * (0.4, 0.5) = (20, 0)
c) 根据sizeDelta=offsetMax-offsetMin, 还可以推导出: anchoredPosition = offsetMin + (offsetMax-offsetMin)*pivot = offsetMin*(1-pivot) + offsetMax*pivot
d) 一般anchors在横向和竖向都没有设置stretch拉伸时,会用anchoredPosition来设置节点坐标:
因为此时, anchorAreaSize为(0, 0), sizeDelta就是节点自身的大小, anchoredPosition就是pivot的坐标(以anchor区域的pivot为原点)
5) Rect rect;

6) Vector3 localPosition;
自己的pivot相对parent的pivot的坐标。
根据localPosition推导出的一些计算公式:
a) 自己的中心点相对于parent的pivot坐标:rtf.localPosition + rtf.rect.center,即图中土黄色向量

b) 自己的中心点相对于parent的左下角: rtf.localPosition + rtf.rect.center + parentRtf.rect.size * parentRtf.pivot,即图中粉红色向量

c) 自己的左下角相对于parent的pivot坐标:rtf.localPosition + rtf.rect.min,即图中土黄色向量

d) 自己的左下角相对于parent的左下角坐标:rtf.localPosition + rtf.rect.min + parentRtf.rect.size * parentRtf.pivot,即图中粉红色向量

e) 自己的左上角相对parent左下角的坐标:rtf.localPosition + rtf.rect.min + parentRtf.rect.size * parentRtf.pivot + new Vector2(0, rtf.rect.size.y),即图中土黄色向量

将节点按中心点对齐
//将a的中心对齐b的中心 public static void SetCenterSameAs(RectTransform rtfA, RectTransform rtfB, Camera uiCam) { Vector3 bLPos = rtfB.localPosition; Vector3 bRectCenter = rtfB.rect.center; Vector3 bCenterLPos = bLPos + bRectCenter; Vector3 bCenterWPos = rtfB.parent.TransformPoint(bCenterLPos); Vector2 bCenterScreenPos = RectTransformUtility.WorldToScreenPoint(uiCam, bCenterWPos); //b中心对应的屏幕坐标 RectTransformUtility.ScreenPointToLocalPointInRectangle((RectTransform)rtfA.parent, bCenterScreenPos, uiCam, out Vector2 aCenterLPos); //相对a父物体pivot的localPosition Vector2 aLPos = aCenterLPos - rtfA.rect.center; rtfA.localPosition = aLPos; }
节点与parent的边距计算
1) 不考虑节点自身缩放时
left边距 = anchorMin.x * parent宽度 + offsetMin.x = 0.2 * 300 + 40 = 100
bottom边距 = anchorMin.y * parent高度 + offsetMin.y = 0.1 * 200 + 30 = 50
right边距 = (1 - anchorMax.x) * parent宽度 - offsetMax.x = (1 - 0.7) * 300 + 10 = 100
top边距 = (1 - anchorMax.y) * parent高度 - offsetMax.y = (1 - 0.9) * 200 + 30 = 50
2) 考虑节点自身缩放

根据边距设置节点坐标
1) 根据上面的推导,我们自己实现的
public static void SetLocalPosByLeftTopMargin(RectTransform rtf, float leftMargin, float topMargin, Rect parentRect) { var rect = rtf.rect; var pivot = rtf.pivot; var localScale = rtf.localScale; var offsetMin = rtf.offsetMin; var offsetMax = rtf.offsetMax; var anchorMin = rtf.anchorMin; var anchorMax = rtf.anchorMax; offsetMin.x = leftMargin - anchorMin.x * parentRect.width - rect.width * pivot.x * (1 - localScale.x); offsetMax.x = leftMargin + rect.width - anchorMax.x * parentRect.width; offsetMin.y = parentRect.height - topMargin - rect.height - anchorMin.y * parentRect.height; offsetMax.y = (1 - anchorMax.y) * parentRect.height + rect.height * (1 - pivot.y) * (1 - localScale.y) - topMargin; rtf.offsetMin = offsetMin; rtf.offsetMax = offsetMax; }
2) RectTransform上其实也有类似的函数
SetInsetAndSizeFromParentEdge
void Start() { var rtf = GetComponent<RectTransform>(); var rect = rtf.rect; rtf.SetInsetAndSizeFromParentEdge(RectTransform.Edge.Left, 100, rect.width); rtf.SetInsetAndSizeFromParentEdge(RectTransform.Edge.Top, 50, rect.height); }
注意:这个函数执行后,会修改anchorMin和anchorMax的值

参考
Unity3D RectTransform使用详解:布局、属性、方法 - 知乎 (zhihu.com)

浙公网安备 33010602011771号