本节书摘来异步社区《unity 3d ngui 实战教程》一书中的第2章,第2.5节,作者: 高雪峰 责编: 张涛,更多章节内容可以访问云栖社区“异步社区”公众号查看。
unity 3d ngui 实战教程
制作ui时,首先我们要创建ui的“根”。在unity顶部ngui菜单中选择create,然后选择2d ui,如图2.25所示。
创建完成后,我们能看到图2.26所示的景象,在scene窗口中,ngui自动生成了一个名为ui root的物体,其中带有一个camera作为子物体。
这个新生成的camera,是ngui生成的专门用来渲染ui的相机,当我们生成ngui的ui root时,就自动将生成的ui的layer设为了第8层。在这个相机中,只能看见第8层的物体,也就是只能看见ui。因为是2d ui,所以我们从图中可以看到相机是正交相机。
图2.26中红色的矩形是相机的视窗大小比例,它会根据game视图中的屏幕长宽比设置自动调整。
创建3d ui的过程和创建2d ui的过程类似,创建出来的3d ui如图2.27所示,ngui依然自动生成了一个名为ui root的物体,并带有一个camera子物体,这个原理和2d ui类似,其中最大的区别就是相机的模式。3d ui的相机在scene视窗中是一个正交摄像机,将会支持ui的三维透视效果。
在我们创建的ui中,可以发现ui root物体和camera物体上面都带有ngui特有的脚本组件,其中ui root物体上带有uiroot和uipanel两个组件,而子物体camera带有一个uicamera组件,这几个组件都是ngui体系中比较核心的组件,下面我们来简单了解一下。
1.uiroot组件
uiroot组件总是出现在ngui的ui“树”的最顶层,也就是那个“根”物体中。它的作用是缩放ui。我们在让美术人员作图时知道,ui一般都是以像素作为单位,比如19201080等,而unity中则是以米为单位,如果一个100100像素的ui元件放入到一块10001000分辨率的屏幕中,按理说这个ui元件应该是屏幕大小的1%,但是因为unity中的单位是米,所以它会从100100像素的大小变为100*100米,会导致一个小ui元件变得非常之巨大。这个时候uiroot会通过屏幕来缩放ui控件,让ui控件从视觉上是正常的。
在uiroot组件中,它提供了3种缩放的方式,也就是uiroot组件下的type值。这3种方式分别为pixelperfect、fixedsize、fixedsizeonmobiles。
pixelperfect是指永远保持像素大小不变,比如一张100100像素的图片,在500500分辨率的屏幕上,它是100100像素,在10001000分辨率的屏幕上,它依然还是100*100像素,因为它的源文件就是这个大小,而pixelperfect让它一直保持这个大小。这样就可以让ui的图片永远是最清晰的,但是会导致分辨率高的屏幕下ui显得特别小;分辨率低的屏幕下ui显得特别大。
fixedsize是和上一种缩放方案完全相反的方案。在fixedsize下,ngui将不再保护图片的原尺寸,只会关心ngui自己所需要的缩放参数,这种模式下必须设置uiroot的manualheight值,然后ngui会将所有的控件按照和这个值的高度比例进行缩放。例如,设置manualheight为1000,然后一张100100的图片在高度为1000的屏幕分辨率下占1/10的高度,那么当ui放到一个分辨率为500500的屏幕上时,它依然占1/10的高度,只不过图片尺寸被自动放缩为50*50,这样就保证了ui和屏幕分辨率的比例是一定的。
fixedsizeonmobiles是两种方案的结合体,它会让ui在pc、mac、linux系统下自动采用pixelperfect,而在移动设备上自动采用fixedsize。
如果没有选择fixedsize,那么必须设置另外两种缩放模式下的minimumheight和maximumheight两个值,代表最大高度和最小高度。例如选择pixelperfect模式,将minimumheight设置为720,将maximumheight设置为900,那么在一个分辨率为800600的屏幕上,因为屏幕分辨率的高度小于uiroot里的最小高度,uiroot就会按照fixedsize模式下manualheight为720的情况进行处理;同理,如果将ui放到一个分辨率为19201080的屏幕上,因为该屏幕分辨率的高度1080大于设置的900,于是uiroot就会按照fixedsize模式下manualheight为900的情况进行处理。
值得注意的是,在3.7.0以后的ngui上,uiroot的缩放模式改为了。
flexible,等同于上文讲到的pixelperfect。
constrained,等同于上文讲到的fixedsize。
constrainedonmobiles,等同于上文讲到的fixedsizeonmobiles。
功能上几乎完全一样。
2.uipanel组件
如图2.28所示,uipanel有很多属性。其中,alpha属性顾名思义是透明度,默认为1不透明。它将控制它旗下所有widget(所有的ui控件都将带有widget,因为它们都继承自widget)的透明度,也就是它会让它的子物体里的所有ui控件都一起发生透明度变化,可以用来做整个ui的淡入淡出以及隐藏等。
depth深度属性,这是一个极其重要的属性。在ngui中,每一个panel都有depth,每一个widget控件也有depth,depth将决定渲染的顺序,直接影响了ui之间的前后重叠关系。depth越高的控件将会显示在视野的上层,depth越高的panel也会显示在视野的上层。但是panel的depth权重远远高于widget,也就是说,在大部分情况下,属于低depth的panel的控件,不管这个控件本身的depth为多少,它都将显示在高depth的panel的控件后面。当你有多个panel的时候,例如你制作了很多面板界面,每一个界面都有一个panel,那么此时尽量保证这些panel不要共用同一个depth,因为这将导致ngui在渲染时无法以1个drawcall完成,会以增加drawcall的方式来保证渲染顺序不混乱,这样就增大了性能的开销。不过ngui在碰到panel有共用depth的情况时会做出提醒,如图2.29红框部分所示。
clipping是剪辑视窗的功能,它将可以让一个面板只显示某一块区域,关于这部分知识后文我们再讲解。
在高级选项中,我们讲解一些初学者需要了解的。render q可以理解为渲染顺序,默认为自动设置。这个选项在和粒子系统结合使用时会有影响,我们后文会说明。如果该panel下的ui需要被灯光影响到(ngui的ui是默认不接收灯光照射效果的),需要勾选normals。如果该panel下面所有的ui控件都不会被移动,那么可以勾选static来将它们设置为静态的,这样会导致该panel下所有的控件都将忽略位置、旋转、缩放的操作,永远保持不动。虽然这样可以提高一些性能,但是慎重使用。
单击show draw calls按钮,可以看到该panel下所有的drawcall消耗情况,如图2.30所示。
3.uicamera组件
图2.31所示为uicamera组件的截图,uicamera这个组件的核心作用是:让带有这个组件的摄像机渲染出的物体能够接收ngui的事件。如果我们自己创建了一个物体,并且希望对这个物体使用一些ngui中的事件,例如onpress()、ondrag()等,就需要为渲染这个物体的摄像机添加uicamera组件。
在uicamera中,大部分设置我们都不需要去操心,它让我们的事件支持多点触摸、鼠标键盘触摸屏等事件的接收。但是要注意的是eventmask这个选项,这个eventmask和相机中的cullingmask非常相似,相机的cullingmask是为了选择渲染那些层的物体,这里的eventmask是为了选择接收那些层的物体的事件。uicamera会默认只接收我们创建ui时被自动设置的那个layer,但是,如果我们在制作ui过程中,在创建ui后因为某些原因修改了ui的层,一定要将uicamera的eventmask修改过来,否则将会发现,我们单击ui没有反应,因为它接收不到这个layer的物体的事件。
关于这3个最基础的控件讲了这么多,其中有很多都是较少用到,主要目的是加快对ngui概念的形成。具体在需要的时候应该进行什么样的操作,我们后面的一些实战内容中会讲到。