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进行操作,如坐标转换、范围测试等等。这里不再展开了。

猜你喜欢

转载自blog.csdn.net/serenahaven/article/details/78826851