UGUI之RectTransform知识点 图解

发表于2015-07-30
评论0 9.1k浏览
       最近因为要做各种UI控件,于是与UGUI杠上了。首当其冲的就是RectTransform,最坑爹的是,
这货竟然不是UGUI框架的,代码竟然封装在unity engine里面,所以,不得不吐槽下unity的开源动
机,根本就是留一手,估计只是因为自己的研发力量不足,所以开放一部分出来而已。
       RectTransform继承于Transform,配合Canvas专门交给UGUI使用,具体这边就不展开了,我
现在也木时间去搞清楚这些乱七八糟的关系。

       直接开讲RecTransform。RectTransform首先要阐述的就是Anchor。
 



        小小的仰慕下设计该解决方案的人,华丽丽的一套思想解决了绝对布局与相对布局的问题。至于
其是不是首创我就不得而知了,本人视野有限,UI方面的东西很是生疏。
        看完了上面的图,我们再来看下这个图:  。你可以
理解为上面那个图是用来让你更好的操作,下面这个才是他的数值。那么,anchor到底是啥,在ugui
里面。
        Anchor名字叫锚点,但在ugui里面其应该叫锚框。其存在最小点与最大点。你可以闭眼想象一
下两个点决定一个矩形,当然也可以决定的是一个点(重合)。如中间的那九个(有人叫他九宫格)
就是最大点与最小点重合。anchormin与anchormax均为向量,那么其向量空间是啥,下面一张图说
明。
          
       其中黑色框子为父物体,红色物体为当前物体。设置红色物体的anchor的时候,其坐标系如图。
(0,0)表征父物体的左下。(1,1)表征右上角。
       如此,你自己动手很好理解中间那九个绝对布局。你还可以手动设置值,让他的锚点位于父物体
的某个位置。那个图你可以理解为预定义的几个锚点位置,当然也是最常用的,一般我们要么居中,
要么就是靠左,靠右的,很少出现非要靠左边1/3处的。
       下面我们来讲解下边上的七个相对布局。相对布局与绝对布局如此和谐的融合主要得益于锚框这
个概念的提出。在ugui中,锚点不再是一个点,而是一个框子,有四个点,用两个点来进行表征。即
anchormin与anchormax,前者表征左下角,后者表征右上角。
           
         观察图,你可以看到锚点已经分为四个点,组成了一个锚框了。这个时候,就是相对布局了,你
的物体会随着父物体变化而变化。
         当使用相对布局的时候,锚框会根据你的输入变换成一个矩形或者一条线,总之四个点各种组合。

         我们观察RectTransform还有一个属性叫pivot,该属性表征的为中心,用3dmax或者maya的人
应该不会生疏这个概念。其向量空间如下图所示:
 
        RectTransform还存在一个属性叫anchoredPosition(anchoredPosition3D此处就忽略不讲了
)。其表征的为锚点到pviot的向量。对于绝对布局很好理解,因为锚点就是一个点,如下图
       首先anchor设置为(0.5,0.5),pivot设置为(0.5,0.5),得到下图:
        
        


       但是对于锚框的情形,如何计算,为此我做了大量的测试,总结,最终得到的结论为:锚点为锚
框根据pviot计算得到,然后再通过锚点计算出pviot相对锚点的偏移向量。有兴趣的可以自行测试下,
我测试的数据如下:
       1、pviot(0.5,0.5),anchor从(0,0)(0,0),(0,0)(0,0.1),(0,0)(0,0.2)……(0,0)
(0,1)得到的anchoredposition的变化为(250.0, 300.0)、(250.0, 275.0)、(250.0, 250.0)、(250.0, 
225.0)、(250.0, 200.0)、(250.0, 175.0)、(250.0, 150.0)、(250.0, 125.0)、(250.0, 100.0)、(250.0, 
75.0)、(250.0, 50.0)。可以看出锚点位于锚框的中心。
       2、pviot(0,0),anchor从(0,0),(0.1,0.1),(0.2,0.2),(0.3,0.3),(0.4,0.4),(0.5,
0.5),(0.6,0.6),(0.7,0.7),(0.8,0.8),(0.9,0.9),(1,1)得到的输出anchoredpoistion
为一直为(150.0, 100.0)
       3、pivot为(1,1),条件同第二条,得到的输出为(350.0, 500.0)、(310.0, 450.0)、(270.0, 400.0)
、(230.0, 350.0)、(190.0, 300.0)、(150.0, 250.0)、(110.0, 200.0)、(70.0, 150.0)、(30.0, 100.0)、
(-10.0, 50.0)、(-50.0, 0.0)。

      至此,anchor与pviot以及anchoredposition介绍完毕。下面就是offsetmin与offsetmax。
offsetmin表征的是图元的左下角相对锚框的左下角的便宜,offsetmax表征图元的右上角相对锚框的
右上角的偏移。如对于绝对布局如下图:
 
    anchor为(0,0.5)
 
anchor为(0,0)
      相对布局如下:

 
anchor为(0,1)(1,1)


        
anchor为(0,0)(1,1)

       再下一个属性是sizeDelta了,“The size of this RectTransform relative to the distances
between the anchors.”写得多直白(吐槽下,官方的英文文档是啥级别的资料组维护的,专业坑爹
三十年么!!!)。这里阐述下,这个属性表示的就是offsetMax-offsetMin得到的向量,即图元从
左下角指向右上角得到的向量。当然如果用的是相对布局的话,这个向量看起来会非常诡异。所以,
这个变量就别用了,属于坑爹API。
       最后一个属性,只读的Rect,其表征的是图元这个Rect,其向量空间为pviot作为原点的xoy坐标
系。目前没觉得有啥大的用途。

      下面来阐述下其中的某些方法:
      void GetLocalCorners(Vector3[] fourCornersArray);该方法表示获取图元的四个角在父物体坐
标系中的坐标。这里有个坑就是你自己要声明一个四个长度的Vector3数组作为参数送进去,方法执行
完毕该数组会被赋值好,依次顺序为从左下开始到右下(如果有旋转的话,另谈)。
      void GetWorldCorners(Vector3[] fourCornersArray);该方法同上,只是获取到的是世界坐标系
的坐标。该方法灰常有用,我上一个项目画写板就是通过这个东西来确定鼠标位于texture的哪一个像
素上,从而完成画写。            
      void SetSizeWithCurrentAnchors(RectTransform.Axis axis, float size);按照的当前的anchor信
息来设置尺寸。其实该方法名字我觉得应该增加上pviot这几个字母,因为实际上你会发现他根据的是
pviot,设置的结果与anchors反而无关,其强大之处也在于此,使用及其方便,你只要设定好pviot,
然后就可以设定其为你想要的范围。很好操控。
      见下图:

      

原位置


pviot(0.5,0.5)


pviot(0,0)

         测试代码:

   
[C#] 纯文本查看 复制代码
1
2
3
4
5
6
7
8
if (Input.GetKeyDown(KeyCode.A))
{
    gameObject.GetComponent<RectTransform>().SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, 200);
}
if (Input.GetKeyDown(KeyCode.S))
{
    gameObject.GetComponent<RectTransform>().SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, 
100);
}
      
       void SetInsetAndSizeFromParentEdge(RectTransform.Edge edge, float inset, float size);这
个函数可以简单的理解为设置图元相对父图元边的距离以及图元的尺寸,其强大之处在于其完全不管
你当前的pviot设置的啥,你的anchor设置的又是啥。例图如下:

原图


图1

 

图二


         测试代码:
[C#] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
if (Input.GetKeyDown(KeyCode.W))
{
    gameObject.GetComponent<RectTransform>().SetInsetAndSizeFromParentEdge(RectTransform.Edge.Top, 
100, 300);
}
if (Input.GetKeyDown(KeyCode.A))
{
    gameObject.GetComponent<RectTransform>().SetInsetAndSizeFromParentEdge(RectTransform.Edge.Left, 
100, 400);
}
if (Input.GetKeyDown(KeyCode.S))
{
    gameObject.GetComponent<RectTransform>().SetInsetAndSizeFromParentEdge(RectTransform.Edge.Bottom,
100, 300);
}
if (Input.GetKeyDown(KeyCode.D))
{
    gameObject.GetComponent<RectTransform>().SetInsetAndSizeFromParentEdge(RectTransform.Edge.Right,
100, 400);
}



QQ截图20150729093602.png (7.41 KB, 下载次数: 0)

QQ截图20150729093602.png

QQ截图20150729102037.png (128.68 KB, 下载次数: 0)

QQ截图20150729102037.png

未标题-9.png (40.79 KB, 下载次数: 0)

未标题-9.png

未标题-10.png (49.56 KB, 下载次数: 0)

未标题-10.png

如社区发表内容存在侵权行为,您可以点击这里查看侵权投诉指引