1. 程式人生 > >UGUI——RectTransform詳解

UGUI——RectTransform詳解

什麼是RectTransform

建立一個UGUI控制元件時,檢視其Inspector面板,原先熟悉的Transform已經被替換成RectTransform,面板也與原先的Transform的面板相去甚遠。

這裡寫圖片描述

先看看Unity官方對RectTransform的描述:

Position, size, anchor and pivot information for a rectangle.
RectTransforms are used for GUI but can also be used for other things. It’s used to store and manipulate the position, size, and anchoring of a rectangle and supports various forms of scaling based on a parent RectTransform.

從官方的描述可以看見RectTransform主要提供一個矩形的位置、尺寸、錨點和中心資訊以及操作這些屬性的方法,同時提供多種基於父級RectTransform的縮放形式。RectTransform用於但不限於GUI,至於GUI以外RectTransform還能怎麼用,不在本篇文章的討論範圍內。

相較於RectTransform,RectTransform提供了更強大的功能來對矩形進行操作,這主要歸功於新增加的兩個概念:Anchor(錨點)和Pivot(中心)。

Anchor(錨點)

錨點(四個)由兩個Vector2的向量確定,這兩個向量確定兩個點,歸一化座標分別是Min和Max,再由這兩個點確定一個矩形,這個矩形的四個頂點就是錨點。

在Hierarchy下新建一個Image,檢視其Inspector。

這裡寫圖片描述

在Min的x、y值分別小於Max的x、y值時,Min確定矩形左下角的歸一化座標,Max確定矩形右上角的歸一化座標。剛建立的Image,其Anchor的預設值為Min(0.5,0.5)和Max(0.5,0.5)。也就是說,Min和Max重合了,四個錨點合併成一點。錨點在Scene中的表示如下:

這裡寫圖片描述

為了看得更清晰,將圖片顏色改為黑色,將Min和Max的值分別改為(0.4,0.4)和(0.5,0.5)。可以看見四個錨點已經分開了。

這裡寫圖片描述

Unity提供了幾個預置的Anchor設定,可以快速地設定。

這裡寫圖片描述

注意到Inspector中Anchor上方的屬性,會隨著我們選擇的Anchor的而變化。因為在不同的Anchor設定下,控制該RectTransform的變數是不同的。

比如設定成全部居中(預設)時,屬性裡包含熟悉的用來描述位置的PosX、PosY和PosZ,以及用來描述尺寸的Width和Height;切換成全部拉伸時,屬性就變成了Left、Top、Right、Bottom和PosZ,前四個屬性用來描述該RectTransform分別離父級各邊的距離,PosZ用來描述該RectTransform在世界空間的Z座標(事實上沒什麼用,它的值不會影響它被渲染的優先程度)。

Pivot(中心)

Pivot用來指示一個RectTransform(或者說是矩形)的中心點。矩形左下角為(0,0),右上角為(1,1)。Pivot為(0,0)時,即與矩形左下角重合。預設狀態下,Pivot為(0.5,0.5),即Pivot在矩形中心。

這裡寫圖片描述

上圖紅框中藍色圓圈表示的就是Pivot。如果無法看見,需要在工具欄中選擇Transform Tools的最後一個選項,或者使用快捷鍵T。

這裡寫圖片描述

可以通過直接在Scene檢視中拖動Pivot來調整錨點位置,也可以在Inspector中直接輸入Pivot的兩個值以得到精確的位置。當對RectTransform進行定位、旋轉和縮放操作時,都將以Pivot為參考點進行。

這裡寫圖片描述

Anchor和Pivot共同作用

子級RectTransform的在父級RectTransfrom中的定位是由子級Anchor和Pivot共同作用完成的。為了方便演示,這裡將原先的Image的Width和Height分別設定成400和300,並改名為ImageParent,然後將它的Anchor設定成預設的左下。再建立一個Image,將顏色設定成綠色,並改名為ImageChild。最後把ImageChild設定成ImageParent的子物體。

現在兩個物體看起來如下:

這裡寫圖片描述

這裡寫圖片描述

現在ImageChild的Anchor重合成一點,並且居於ImageParent的正中心。拖動ImageChild,讓它相對於Anchor有一定的偏移,然後選中ImageParent,更改其位置和大小,觀察變化:

這裡寫圖片描述

可以發現,ImageChild將保持與Anchor的相對位置不變,其尺寸不會發生變化。

在Anchor重合成一點的情況下,我習慣將它稱之為“絕對定位”(事實上它依舊是相對的,相對於父級RectTransform。比如某些情況,Canvas確定了,某個RectTransfrom直接掛在Canvas下,那它的定位就是相對於一個固定的RectTransform,也就可以被看作絕對定位了)。

回過來看看ImageChild的Inspector面板,確定其位置和尺寸的屬性如下:

這裡寫圖片描述

也就是說,在錨點全部重合的情況下,PosX、PosY和PosZ確定了它的Pivot相對於Anchor的位置,Width和Height確定了它的尺寸。

四個錨點重合這種情況是比較好理解的,再看看Anchor兩兩重合的情況。

將ImageChild的Anchor修改為居中左右拉伸,如圖:

這裡寫圖片描述

RectTransform的定位屬性由原先的PosX改為Left、原先的Width改為Right。並且我們可以通過點選這些屬性看到Scene檢視中這些值的視覺化顯示。

由於我們現在設定的Anchor是左右拉伸,因此,在改變ImageParent的尺寸時,ImageChild的橫向尺寸將根據需要進行拉伸或壓縮,但是在豎向上,ImageChild依舊依靠PosY和Height來指定它的Y軸位置和高度。

這裡寫圖片描述

也就是說,在僅左右拉伸的情況下,子RectTransform的左邊和右邊會分別與其左右兩個Anchor保持Left和Right的距離;相對於兩個Anchor連線的豎直偏移由PosY確定;自身的高度由Height確定。

明白了這種Anchor的設定,其他兩種情況也就類似了。讀者可以自行嘗試。

在僅上下拉伸的情況下,子RectTransform的上邊和下邊會分別與其上下兩個Anchor保持Top和Bottom的距離;相對於兩個Anchor連線的水平偏移由PosX確定;自身的寬度由Width確定。

在上下左右均拉伸的情況下,子RectTransform的上下左右會分別與其上下左右四個Anchor保持Top、Bottom、Left和Right的距離;其位置和尺寸完全由父RectTransform控制。

position、localPosition、anchoredPosition和anchoredPosition3D屬性

Transform有positionlocalPosition屬性,這兩個分別代表在世界空間的絕對位置和相對於父級物體的相對位置。RectTransform引入了anchoredPositionanchoredPosition3D,它們都是相對位置,但是相對的是自身的Anchor。

當錨點全部重合時,anchoredPosition代表的就是自身Pivot到Anchor的向量。

這裡寫圖片描述

這裡寫圖片描述

anchoredPositionanchoredPositoin3D都可以認為是以畫素為單位。

關於RectTransform的positionlocalPosition,它們的值根其所屬的Canvas的渲染模式有關。

在Screen Space——Overlay的模式下,由於Canvas的世界尺寸與其畫素尺寸在數值上相等,因此其rectTransformposition與其在螢幕空間的座標在數值上也相等。這種模式下,要獲取某個RectTransform的螢幕座標,直接使用position就可以。

在Screen Space——Camera的模式和World Space下,RectTransform的渲染與攝像機有關,在獲取其螢幕座標時,需要利用canvas.worldCamera,或者transform.TransformPoint等座標轉換函式進行座標轉換。

offsetMax和OffsetMin屬性

先看看官方的說明:

offsetMax The offset of the upper right corner of the rectangle relative to the upper right anchor.
offsetMin The offset of the lower left corner of the rectangle relative to the lower left anchor.

意思很明確了,offsetMax是RectTransform右上角相對於右上Anchor的距離;offsetMin是RectTransform左下角相對於左下Anchor的距離。

這個值在使用程式碼控制RectTransform時很有用,比如在製作UI時,其中有個RectTransform採用的是“絕對定位”,執行時需要用程式碼來將其設定為全拉伸,那麼對該RectTransform執行如下操作就可以實現:

	rectTransform.anchorMin = Vector2.zero;
	rectTransform.anchorMax = Vector2.one;
	rectTransform.offsetMin = Vector2.zero;
	rectTransform.offsetMax = Vector2.zero;

offset可以認為是以畫素為單位。

sizeDelta屬性

sizeDelta是個由引擎計算出來的值,這個值很容易被錯誤地使用。要正確地使用sizeDelta,就要先理解它是怎麼算出來的。

The size of this RectTransform relative to the distances between the anchors.
If the anchors are together, sizeDelta is the same as size. If the anchors are in each of the four corners of the parent, the sizeDelta is how much bigger or smaller the rectangle is compared to its parent.

sizeDeltaoffsetMax-offsetMin的結果。在錨點全部重合的情況下,它的值就是面板上的(Width,Height)。在錨點完全不重合的情況下,它是相對於父矩形的尺寸。

一個常見的錯誤是,當RectTransform的錨點並非全部重合時,使用sizeDelta作為這個RectTransform的尺寸。此時拿到的結果一般來說並非預期的結果。

sizeDelta可以認為以畫素為單位。

rect屬性

如果想要獲取一個RectTransform的矩形資訊,應該使用rectTransform.rect屬性。

rect屬性同樣是一個計算出來的值,但是它表示的是該rectTransform對應的矩形的相關資訊。其中前兩個引數分別代表矩形左下角相對於錨點的x和y座標,後兩個引數分別代表舉行的寬度和高度。

rect可以認為是以畫素為單位。

RectTransformUtility

RectTransformUtility是原生的RectTransform工具,它提供了多個靜態函式來對RectTransform進行操作,如座標轉換、範圍測試等等。這裡不再展開了。