Unity UGUI中RectTransfrom中锚点(Anchor)、中心(Pivot)、Rect及坐标分析

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的值计算得出)
--------------------- 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Unity3D,uGUI是一个用户界面系统,它可以让开发者创建和管理游戏的UI元素,如按钮、文本等。在uGUI,世界坐标是指相对于场景原点的坐标系,而屏幕坐标是指相对于屏幕的坐标系。 在实际运用,我们可以通过以下方式将世界坐标转换为屏幕坐标: ```csharp Vector3 worldPosition = new Vector3(10, 5, 0); Vector3 screenPosition = Camera.main.WorldToScreenPoint(worldPosition); ``` 这里我们使用了Camera.main.WorldToScreenPoint()方法,将世界坐标转换为屏幕坐标。这个方法需要指定一个摄像机,它将根据该摄像机的位置和朝向来计算屏幕坐标。在这个例子,我们使用的是场景的主摄像机,也就是Camera.main。 同样地,我们也可以将屏幕坐标转换为世界坐标: ```csharp Vector3 screenPosition = new Vector3(100, 100, 0); Vector3 worldPosition = Camera.main.ScreenToWorldPoint(screenPosition); ``` 这里我们使用了Camera.main.ScreenToWorldPoint()方法,将屏幕坐标转换为世界坐标。同样地,这个方法也需要指定一个摄像机。 在实际开发,我们可以使用这些方法来处理鼠标点击、UI元素的位置调整等操作。例如,我们可以通过以下代码来将一个UI元素移动到鼠标点击的位置: ```csharp public void OnPointerClick(PointerEventData eventData) { Vector3 worldPosition = Camera.main.ScreenToWorldPoint(eventData.position); transform.position = worldPosition; } ``` 这里我们使用了Unity3D的事件系统,当鼠标点击时,OnPointerClick()方法会被调用。在这个方法,我们通过Camera.main.ScreenToWorldPoint()方法将屏幕坐标转换为世界坐标,然后将UI元素的位置设置为该世界坐标。这样,当我们点击鼠标时,UI元素就会移动到鼠标点击的位置。 总之,在uGUI,世界坐标和屏幕坐标的转换是非常重要的,它们可以帮助我们处理一些常见的UI操作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值