Unity UGUI中RectTransfrom中锚点(Anchor)、轴心(Pivot)、Rect及坐标分析
标签(空格分隔): unity3d
1 RectTransform.pivot
Pivot:物体的轴心,这里千万不要把这个参数理解为了物体中心,这个跟物体的中心是有区别的,当在设置锚点的位置为居中时,是根据父物体中心来计算,而不是这里的Povit计算的,在后面会详细说明。
具体这个值的调整方式、方法,太简单了,这里就不记录了。
2 RectTransform.anchoredPosition
anchoredPosition :锚点位置,从锚点中心(这里不是锚点的中心,后面关于这个地方有更正说明)到本物体的轴心(Pivot)的向量值
Inspector配置如图:
显示结果如图:
关于锚点位置,首先是左上角custom的那个小窗口,可以设置默认的锚点位置值,比如居中,居左,stretch(平铺)等方式。
这里选择的是将锚点设置为左下角。那么第一个疑问点出现了,这里的左下角是指的相对于谁的左下角?
通过图中的锚点(左下角那四个白色透明的三角形)可以看出,这里选择的左下角、居中、居左甚至stretch,都是以其父窗口为参考。也就是说,如果设置锚点居中,则是将锚点的位置设置为其父窗口的几何中心而不是父窗口的Pivot。
关于这一点有兴趣的同学可以自己做实验试试,改变父窗口的Pivot,子窗口的锚点位置及值是不会改变的。
同理,如果将锚点设置为左下角,则锚点的位置将位于父窗口的左下角,而不是本窗口的左下角。
搞清楚了锚点位置的选取参考物后再来分析锚点的值:RectTransform.anchoredPosition的具体含义。之前一直对这个没有搞清楚,翻看了几篇大神的帖子后算是彻底搞明白了。回到第二幅图,图中锚点(左下角的四个三角形)的值为(200,200),也就是RectTransform.anchoredPosition的值为(200,200)。这个值等于锚点到本控件的Pivot的向量值,如第二幅图中的红色箭头所示。
如果我们固定锚点位置,改变Pivot的值,那么RectTransform.anchoredPosition的值会跟随变化,如图:
将Piovt的x改为0,则锚点的值变为了50
这里,感觉好像完全搞清楚了锚点位置,以及RectTransform.anchoredPosition的意义了,其实不是!!!这里还有一个问题,锚点不仅可以是这样的:
还可以是这样的:
锚点其实不是一个点,其实是四个钉子!!!
当我们使用Stretch的方式时,锚点就不再是四个聚在一起的点了,而是分开的,那么这里RectTransform.anchoredPosition的值怎么算? 根据实验测试结果,这个时候的RectTransform.anchoredPosition值应该是四个钉子的几何中心到本控件的Pivot的矢量值,如下图所示。
其实从程序开发的角度来看,符合美学的软件应该是用一个抽象的模型,计算出正确的结果,那么这里,作为符合美学的软件必然不会讲这个问题区分成if(集中型锚点)xxx……,if(分散型锚点)xxx……这种丑陋的实现方式。所以,这里我觉得可以大胆的推测Unity在这里的实现,始终是取四个钉子的几何中心点,然后从该点向Povit点做向量,将向量的值记录在RectTransform.anchoredPosition里。
所以这里再回头看本章第一句话的描述:“anchoredPosition :锚点位置,从锚点中心到本物体的轴心(Pivot)的向量值”其实这里的锚点中心,就是指的四个钉子的几何中心点。
之前这里搞错了,在此更正 :
这里主要更正锚点位置的计算方式,锚点位置的计算方式应该跟物体的轴心计算方式相同,只是轴心的参考物为本控件的Rect,而锚点的参考物为锚点的四个钉子组成的Rect。
anchoredPosition的值不是四个钉子的几何中心到本控件的Pivot的矢量值,而是四个钉子形成的矩形上的某一个点到控件的Pivot的矢量值。
锚点的这个点的确定也是依赖Pivot值的,即:锚点的最终位置为由四个钉子组成的矩形的Pivot位置,假设当前红色矩形的Pivot为(0.2, 0.2),则anchoredPosition值如下图所示:
anchoredPosition的值最终为(80,-10)。
3 RectTransform.offsetMax/offsetMin
RectTransform.offsetMax : (x, y)
RectTransform.offsetMin : (x, y)
这两个值表示四个钉子(锚点)(注意这里的描述,四个钉子!!一定要把锚点理解为四个点,而不是一个点),到本控件上对应顶点的矢量的最大值与最小值。
怎么理解这句话?
1、锚点对应的控件顶点
这个地方是本人的猜测或者说是假设,但是也是符合实际情况的,同时也是我觉得这里的代码如果要优雅的实现,这样的模型是一个比较优雅的实现方式。
所谓对应,即:锚点其实是四个钉子,分为左上,左下,右下及右上四个,每个空间在UI模型中都是一个矩形,也有左上,左下,右下及右上四个顶点,那么锚点的每个钉子可以关联一个点,即左上————左上;左下————左下;右下————右下;右上————右上。这样进行绑定。
2、offsetMax、offsetMin的值哪里来
理解了1中的锚点与控件顶点绑定关系后,那么offsetMax、offsetMin的求解规则就很简单了。
首先计算锚点的每个钉子到其对应的顶点矢量值,分别记作v0,v1,v2,v3,如图所示:
然后比较四个向量的x值,将x的最大值赋给offsetMax.x,将x的最小值赋给offsetMin.x;y的值同理。
这么说,应该就很好理解为什么stretch模式和点模式的时候,offsetMax、offsetMin的值风格完全不一样的问题了,看上去好像不同,其实本质是一个模型。
4 RectTransform.sizeDelta
这个值没什么说的了:
sizeDelta.x = offsetMax.x - offsetMin.x;
sizeDelta.y = offsetMax.y - offsetMin.y;
这里就是要提醒一点,当锚点为点模式时(非stretch),sizeDelta的值等于RectTransform.rect.size的值,而当锚点为stretch类型时,sizeDelta的值不等于*RectTransform.rect.size的值,所以我看到有人的博客上说可以通过改变sizeDelta的值来调整控件的size,这个我觉得只说对了一半,另一半是:当控件的布局为stretch类型时sizeDelta与控件的size负相关,在调整的时候要谨慎谨慎谨慎*!!!至于原因,就上本文上述的前几章的吧啦吧啦。
5 RectTransform.rect
RectTransform.rect的各值如图所示。
其中RectTransform.rect.position的值为本控件的pivot点到左下角点的向量的值,size的值的求法如下图所示:
图中最下面的公式就是size值的求法,其中p’op’1这条向量的值对应的就是size的值。这里给出的是一个通用解法,我猜测unity的代码实现应该是用的类似的思路,这样一个公式就可以适应所有的情况。但是如果是人来算的话其实不用这么麻烦,看一眼就知道size有多大了……
6 RectTransform.anchorMax/anchorMin
锚点是四个钉子,再次回到这个话题。
anchorMax : (x, y)
anchorMin : (x, y)
anchorMin.x表示锚点在x轴的起始点位置,anchorMax.x表示锚点在x轴的终点位置,取值0~1,表示百分比值,该值乘以父窗口的width值就是实际锚点相对于父窗口x轴的位置。y轴与x轴同理。
这个值确定了锚点相对于父窗口的位置,是真正决定锚点位置的值
7 控件位置是如何确计算的
作为人而言,最直观的坐标位置就是RectTransform.rect.position值,也就是控件的左下角点的位置,再加上控件的长、宽值来确定控件最终的位置,那么如何计算这些值,最后在这里总结一下:
父物体rect–>确定本控件锚点位置(由RectTransform.anchorMax/anchorMin决定)–>确定pivot位置(由RectTransform.anchoredPosition决定)–>得到本控件Rect.position的值(由Rect.size及pivot的值计算得出)