Unity——RectTransform詳解

前言

最近一段時間的實(shí)習(xí)都是苦逼的在做ui,做移動端的,適配是永恒的話題,慶幸的是unity提供了一套強(qiáng)大的接口讓開發(fā)者來很好的實(shí)現(xiàn)自己想要適配的效果,曾經(jīng)的我認(rèn)為 用代碼做適配是不可能的,這輩子都不可能的,最多拖一拖錨點(diǎn)這個樣子 ,現(xiàn)在熟悉了之后只有兩個字 真香。希望各位看官看完這篇文章后也能不再害怕unity的布局系統(tǒng)。


本文講解順序

  • 1.Anchor(Min,Max)
  • 2.絕對與相對布局
  • 3.Pivot
  • 4.Offset(Min,Max)
  • 5.SizeDelta
  • 6.rect
  • 7.anchoredPosition
  • 8.Recttransform類中一些方法的介紹
    趕時間的看官可以直接跳到感興趣的部分

1.Anchor

unity中的ui元素是有嚴(yán)格的父子關(guān)系的,子物體的位置是根據(jù)父物體的變化而變化的,而子物體和父物體聯(lián)系的橋梁就是Anchor。在recttransform面板中可以調(diào)整錨點(diǎn)的值

image.png

為什么一個點(diǎn)會由四個值來確定呢,其實(shí)Anchors準(zhǔn)確來說是由兩個點(diǎn)確定的。他們就是AnchorMin以及AnchorMax
image.png
之所以anchorMax和anchorMin的值是小數(shù),是因?yàn)槠浔碚鞯氖窃擖c(diǎn)所在位置占父物體大小的比例,也就是圖中黑色畫線部分占灰色物體總長度和總寬度的比例,所以在示意圖的情況下
二者的值為:anchorMax(0.5,0.5),anchorMin(0,0) (默認(rèn)左下角為0,0點(diǎn),右上角為1,1點(diǎn))

為了方便后續(xù)描述,我把Anchor分為兩種情況

  • 當(dāng)anchorMax與anchorMin相等時,Anchor呈現(xiàn)為一個點(diǎn),我稱之為錨點(diǎn)
  • 當(dāng)anchorMax與anchorMin不相等時,Anchor呈現(xiàn)為一個框,我稱之為錨框(即示意圖中的情況)

2.絕對與相對布局

想要清晰的理解Recttransform的各個屬性,個人認(rèn)為首先需要建立的第一個概念就是絕對布局以及相對布局這兩個概念。

2.1絕對布局

所謂的絕對布局,就是出現(xiàn)錨點(diǎn)的情況,此時的recttransform面板中的屬性變成了

image.png

PosX,PosY,PosZ,Width,Height,這五個屬性,首先說說WidthHeight,在絕對布局的情況下無論分辨率是多少,父物體多大,該UI元素的大小是恒定的,如下圖所示
image.png

image.png

而剩下的PosX,PosY,PosZ表征的就是Pivot (第三部分有關(guān)于Pivot的講解) 到錨點(diǎn)的距離
image.png
image.png

所以如果使用了絕對布局,在采用不同分辨率的時候,該元素的大小恒定,可能就會出現(xiàn)在高分辨率情況下元素太小或者低分辨率情況下元素比屏幕大的情況。

2.2相對布局

所謂相對布局,就是出現(xiàn)錨框的情況。在這種情況下UI元素的四個角,距離四個對應(yīng)的錨點(diǎn)的距離是不變的,在這種情況下RectTransform的屬性又變?yōu)榱?code>Left,Top,Right,Bottom,PosZ,其中的PosZ表征的是該元素到父物體在Z軸上的偏移,利用這個值可以調(diào)整UI元素的顯示順序,不過我用的不多,這里不作太多討論。剩下的四個值應(yīng)該很好理解了,就是UI元素的每一條邊距離父物體的每一條邊的距離。
在示意圖的情況下,我設(shè)定了紅色圖片(子物體)距離灰色圖片(父物體)的每一條邊的距離都是200個單位。

image.png
image.png

接下來我們將灰色的圖片(父物體)縮小,看看紅色圖片的變化
image.png

我們會發(fā)現(xiàn)紅色的圖片縮小了,但是其每個邊距離父物體的距離是不變的,這個就是所謂的相對布局。
image.png

如果有同學(xué)出現(xiàn)這種情況,那就是因?yàn)?code>Top和Bottom的值加起來比父物體的高還要高,所以計(jì)算子物體高的時候出現(xiàn)負(fù)數(shù)的情況,就會出現(xiàn)這種叉叉的情況,只要還原父物體的大小就ok(橫向同理)。

3.Pivot

Pivot中心點(diǎn),就是該UI元素旋轉(zhuǎn)縮放的中心點(diǎn),左下角為(0,0)右上角為(1,1)

image.png
image.png
image.png

所以之前在絕對布局的情況下,PosXPosY的值就是Pivot到錨點(diǎn)的值,Pivot這個屬性應(yīng)該是RectTransform那么多屬性中最好理解的一項(xiàng)了吧!

4.Offset

首先說說OffsetMax,其實(shí)OffsetMin也是同理。接下來會主要解釋兩個問題

OffsetMax的值是怎么計(jì)算得出來的呢?OffsetMax又有什么用呢?

  • 其實(shí)沒有那么神秘,這個值就是UI元素的右上角的坐標(biāo),減去AnchorMax的值,得到一個從AnchorMax指向元素右上角的向量(vector2類型),各位看官可以自行測試一下。
    image.png
  • 那么這個值有什么用呢,因?yàn)檫@個值是一個可讀可寫的屬性,所以在錨框的情況下我們可以在代碼里面動態(tài)的去調(diào)整UI元素相對邊界的距離,其次更重要的是,利用這這兩個值就可以計(jì)算出sizeDelta的值了!

5.sizeDelta

以前對這個屬性是真的一臉懵逼,網(wǎng)上很多教程說這個值可以設(shè)置UI元素的大小,但是真的有時候好用,有時候有不好用,真的一頭霧水,官方文檔說的也是很籠統(tǒng),但是現(xiàn)在搞清楚了其中的聯(lián)系以后,就覺得清晰了不少了。

其實(shí)sizeDelta的值就是OffsetMax-OffsetMin的值

所以就會出現(xiàn)有時候sizeDelta得到的是UI元素的大小,有時候又不是的情況,下面就復(fù)現(xiàn)一下這兩種情況

5.1錨點(diǎn)情況下的sizeDelta

image.png

在錨點(diǎn)情況下,offsetMax和Min的起點(diǎn)相同,根據(jù)向量相減的三角形法則(不記得是不是這樣說得了哈哈哈),可以得到一個新的向量,這個新的向量的X和Y的大小正好UI元素的寬和高相等,所以在這個時候去設(shè)置sizeDelta的值,可以直接調(diào)整UI元素的大小

5.2錨框情況下的sizeDelta

image.png

在錨框的情況下,offstMax減去Min,得到的將不再是UI元素的大小,而是一個新的奇怪的向量,這個向量代表的物理意義是,sizeDelta.x值就是錨框的寬度與UI元素的寬度的差值,sizeDelta.y的值就是錨框的的高度與UI元素的高度的差值

所以這個屬性之所以叫做sizeDelta,是因?yàn)樵阱^點(diǎn)情況下其表征的是size(大小),在錨框的情況下其表征的是Delta(差值)

那么我們在錨框的情況下要怎么樣才能獲得元素的大小呢?這個時候就可以用到rect屬性了。

6.rect

rect中的屬性,不與UI元素所在的位置有關(guān),只和其自身屬性相關(guān),所以其中的rect.widthrect.height屬性就可以讓我們在任何情況下取得元素的大小,而rect.xrect.y如圖所示,表示的是以Pivot為原點(diǎn),UI元素左下角的坐標(biāo),可以看到圖中Pivot是在UI元素的正中間,所以左下角的坐標(biāo)就剛好是(-100,-100)

image.jpg

但是有一個問題,rect屬性是一個只讀的屬性,如果我們想要設(shè)置UI元素的大小的話,這好像又不適用了,所以RectTransform還提供了幾個非常有用的方法。

7.anchoredPosition

通過直接設(shè)置anchoredPosition的值可以改變UI元素的位置,但也是要分錨點(diǎn)錨框的情況

在使用錨點(diǎn)的情況下,anchoredPosition表征的是元素Pivot到Anchor的距離

 private RectTransform rectTransform;
    // Use this for initialization
    void Start()
    {
        rectTransform = GetComponent<RectTransform>();
        rectTransform.anchoredPosition = new Vector2(0, -100);
    }
image.png

在使用錨框的情況下,anchoredPosition表征的是元素Pivot到錨框中心點(diǎn)的距離

image.png

8.Recttransform類中一些方法的介紹

8.1 SetSizeWithCurrentAnchors(Animations.Axis axis, float size)

這個方法無論在絕對布局還是相對布局的情況下,都可以通過直接設(shè)置rect中的widthheight值來改變UI元素的大小。

private RectTransform rectTransform;
    // Use this for initialization
    void Start()
    {
        rectTransform = GetComponent<RectTransform>();
        rectTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, 100);
        rectTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, 100);    
    }

8.2 SetInsetAndSizeFromParentEdge(RectTransform.Edge edge, float inset, float size)

這個方法就比較冷門了可能,不過還是挺強(qiáng)大的。調(diào)用這個方法,可以根據(jù)父物體的Edge(某一邊)去布局。其中第一個參數(shù)就是用于確定基準(zhǔn)的邊,第二個參數(shù)是UI元素的該邊界與父物體該邊界的距離,第三個元素是設(shè)定選定軸上UI元素的大小,可能說起來有點(diǎn)復(fù)雜,但是我上兩張圖相信各位就可以秒懂了。

首先以右邊界為基準(zhǔn)

  private RectTransform rectTransform;
    // Use this for initialization
    void Start()
    {
        rectTransform = GetComponent<RectTransform>();
        rectTransform.SetInsetAndSizeFromParentEdge(RectTransform.Edge.Right, 200, 400);
        //這種情況下我選定父物體的右邊界為基準(zhǔn),結(jié)果如下圖
    }
image.png

然后以下邊界為基準(zhǔn)

 private RectTransform rectTransform;
    // Use this for initialization
    void Start()
    {
        rectTransform = GetComponent<RectTransform>();
        //rectTransform.SetInsetAndSizeFromParentEdge(RectTransform.Edge.Right, 200, 400);
        rectTransform.SetInsetAndSizeFromParentEdge(RectTransform.Edge.Bottom, 200, 400);
    }
image.png

在使用這個方法的時候要注意錨點(diǎn)也會改變,改變的規(guī)則為

  • 以左邊界為基準(zhǔn)時,anchorMinanchorMaxy不變x變?yōu)?.
  • 以右邊界為基準(zhǔn)時,anchorMinanchorMaxy不變x變?yōu)?.
  • 以上邊界為基準(zhǔn)時,anchorMinanchorMaxx不變y變?yōu)?.
  • 以下邊界為基準(zhǔn)時,anchorMinanchorMaxx不變y變?yōu)?.

8.3 GetWorldCorners(Vector3[] fourCornersArray)

使用這個方法,可以取得UI元素四個角的世界坐標(biāo),具體使用方法,先建立一個長度為4的vector3數(shù)組,然后傳進(jìn)這個方法,調(diào)用一次后,數(shù)組被賦值,里面的四個元素分別是UI的左下角左上角,右上角,右下角。

  private RectTransform rectTransform;
    // Use this for initialization
    void Start()
    {
        rectTransform = GetComponent<RectTransform>();
        Vector3[] corners = new Vector3[4];
        rectTransform.GetWorldCorners(corners);
        foreach (Vector3 corner in corners)
            Debug.LogWarning(corner);
    }
image.png

最后

寫到這里rectTransform中比較重要的屬性和方法都大概介紹完了,這畢竟是我第一次那么正正經(jīng)經(jīng)的寫博客,有紕漏之處還請各位大神指正,有什么不清楚的地方可以私信我,最后祝大家學(xué)習(xí)愉快哈哈哈!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容