UGUI簡述
UGUI主要提供了兩個能力
- UI元素的渲染與適配(其中UI元素的Mesh中的position資訊就是通過RectTransform生成的,本文重點)
- 裝置事件的響應與處理(EventSystem系統,及封裝的Button、Toggle等常用元件)
RectTransform序列化的內容
也就是說RectTransform是通過這四個屬性來確定RectTransform的四個頂點的(position)。
如何確定頂點資訊
額外屬性的含義
- anchorMin:左下角錨點距離父節點左下角的標準距離(父節點所確定四個頂點的矩形的左下角看作(0,0),右上角看作(1,1))。
- anchorMax:右上角距離父節點左下角的標準距離。
- pivot:中心點距離自身所確定的矩形的左下角的標準距離。
- sizeDelta:自身所確定的矩形長寬相對於anchorMin、anchorMax所確定的矩形的偏移量(偏移時會按照pivot的比例來偏移,舉個例子:pivot是(0.3,pY),sizeDelta是(100, sY),那麼自身的矩形左下角會相對於anchorMin負向偏移30,右上角會相對anchorMax正向偏移70,整體將矩形擴大了100。y軸一樣)。
- anchoredPosition:自身矩形的中心點相對於anchorMin、anchorMax所確定的矩形中心點的位置(或者也可以理解為偏移量,下面會說)
如何通過這幾個引數來確定自身的矩形
通過一個例子來說明一個RectTransform的形狀是如何通過上面的幾個引數確定的。
父節點資訊
子節點資訊
1.確定anchorMin、anchorMax代表的矩形
父節點的長寬為(1920,1080),子節點的anchorMin為(0.2,0.3),所以如果把父節點矩形的左下角看作原點,那麼anchorMin所代標的點的座標即為(1920 * 0.2,1080 * 0.3),也就是(384,324)。同理,得到anchorMax代表點的座標(1152,972)。
也就是一個左下角座標為(384,324),長寬為(1152 - 384,972 - 324),即(768,648)的矩形。
用RectTransform來表示的話就是下圖這樣,anchorMin、anchorMax、pivot都為(0,0),Pos為(384,324),長寬(768,648)。
2.通過sizeDelta和pivot確定自身矩形的大小
因為sizeDelta是(100,300),所以接下來對上一步確定的矩形的左下角平移(-100 * 0.4, -300 * 0.5),平移後為(344,174)。右上角的點平移(100 * 0.6, 300 * 0.5),平移後為(1212,1122)。
用RectTransform來表示的話就是下圖這樣,anchorMin、anchorMax、pivot都為(0,0),Pos為(344,174),長寬(868,948)。
3.通過anchoredPosition對自身進行平移
把上一步確定的矩形平移子節點的anchoredPositino(60,-200)。
用RectTransform來表示的話就是下圖這樣,anchorMin、anchorMax、pivot都為(0,0),Pos為(404,-26),長寬(868,948)。
這個RectTransform所表示的矩形正好可以和子節點的重合,雖然引數不一樣。
注意
嚴格來說並不是左下角或者右上角,而是指的anchorMin、anchorMax所確定的點。向左、向右指的是父節點空間內的負方向和正方向。但是因為絕大多數情況下anchorMin的xy座標會小於anchorMax的xy座標,這樣才是一個幾何意義明顯的矩形。
RectTransform的Inspector皮膚
- 就是anchorsMin、anchorsMax、pivot,上面已經說過了,這理解不說了。
- 是就是Transform的localRotaion和localScale屬性,也沒啥好說的。
- 這四個數值是對sizeDelta和anchoredPosition的封裝。讓開發者可以更直觀的進行位置和大小的調整。
具體來說就是左側的兩個值代表了sizeDelta和anchoredPosition的x值,右側的兩個值代表了y值。
下面就來說一下左邊兩個值的具體含義,當anchorsMin和anchorsMax的x值相等時,也就是這兩個錨點的x座標重合。這個時候這兩個值會變成PosX和Width,其實就是anchoredPosition.x和sizeDelta.x的幾何意義。
anchoreMin和anchoreMax的x值不等時,也就是這兩個錨點的x座標分離時。會變成left,right。分別代表子節點左側、右側相對於anchoredMin、Max確定的矩形向內的偏移量,十分直觀。其實還是對anchoredPosition.x和sizeDelta.x的封裝。
右邊的兩個值就對應anchoredPosition.y和sizeDelta.y。 - 就是localPosition的z值。在Inspetor中,把localPostion.xy隱藏了,只暴露了z值出來,因為localPositino的xy值一般不會主動去修改,是通過RectorTranform中這幾個額外的屬性動態算出來的。
- 一些預設的常用值,縱向代表y,橫向代表x。
- 這兩個按鈕是藍圖模式和原始模式,藍圖模式就是在Scene中的那個小框是把RectTranform包起來,還是展示通過這幾個額外屬性確定的矩形(不考慮旋轉和縮放)
原始模式就是在調整anchors和pivot的時候是否需要動態調整sizeDelta和anchoredPosition來保持該節點的矩形區域不變。選中時代表不動態調整。
localPosition與anchoredPosition的關係
localPosition就是tranform所確定的座標系原點在父tranform所確定的座標系下的位置。在RectTransform中,自身所確定的座標系原點位置在RectTransform確定的矩形的中心。
所以在RectTranform下,localPosition也可以理解為自身矩形與父節點確定的矩形中心的相對位置(偏移量)。
localPosition與anchoredPosition的轉換
先建立以父節點左下角為原點的座標系o。
定義:
childPivotPos代表子節點中心點在o中的座標。
parentPivotPos代表父節點中心點在o中的座標。
anchorsPivotPos代表子節點anchors確定的矩形的中心點在o中的座標。
則有:
localPosition.xy
= childPivotPos - parentPivotPos
= (childPivotPos - anchorsPivotPos) + (anchorsPivotPos - parentPivotPos)
= anchoredPosition + (anchorsPivotPos - parentPivotPos)
= anchoredPosition + anchorsPivotPos相對於父節點中心的偏移量
接下來就可以實際上進行計算了。
定義:
pSize代表父節點的長寬(除了根Canvas外,其他所有的RectTransform所確定的矩形都是依賴於父節點的。所以我們跳過父節點矩形的計算,直接用rect屬性獲取父節點長寬)。
pPivot代表父節點的pivot。
cAnchorsMin、cAnchorsMax、cPivot代表子節點的anchorsMin、anchorsMax、pivot。
則有:
parentPivotPos = Vector2.Scale(pSize, pPivot)
anchorsPivotPos = Vector2.Scale(pSize, cAnchorsMin) + Vector.Scale(pSize, (cAnchorsMax - cAnchorsMin) * cPivot)
anchorsPivotPos - parentPivotPos = Vector2.Scale(pSize,cAnchorsMin + (cAnchorsMax - cAnchorsMin) * cPivot - pPivot)
簡單測一下,隨便調調父節點和子節點的屬性。
public class PositionTest : MonoBehaviour
{
public Vector3 localPosition;
public Vector2 anchoredPosition;
public Vector3 delta;
public Vector3 calculation;
// Update is called once per frame
void Update()
{
var parentRectTrans = (transform.parent as RectTransform);
var rectTrans = transform as RectTransform;
localPosition = rectTrans.localPosition;
anchoredPosition = rectTrans.anchoredPosition;
//差值
delta = (Vector2)localPosition - anchoredPosition;
//通過公式計算的插值
calculation = Vector2.Scale(
parentRectTrans.rect.size,
rectTrans.anchorMin + (rectTrans.anchorMax - rectTrans.anchorMin) * rectTrans.pivot - parentRectTrans.pivot
);
}
}