《Unity3D高级编程 主程手记》第四章 用户界面(二) UGUI 系统的原理及其组件使用
目录
(2)Screen Camera模式——以 Camera 为基准
UGUI 系统的运行步骤
UGUI 是在 3D 网格下建立起来的 UI 系统,它的每个可显示的元素都是通过 3D 模型网格的形式来构建起来的。当 UI 系统被实例化时,UGUI 系统首先要做的就是构建网格。
过程
Unity3D 在制作一个图元,或者一个按钮,或者一个背景时,都会先构建一个方形网格,再将图片放入网格中。可以理解为制造了一个 3D 模型,用一个网格绑定一个材质球,材质球里存放要显示的图片。
问题
如果每个元素都生成一个模型并且绑定一个材质球存入一张图片的话,那么界面上成千上万个元素就会拥有成千上万个材质球,以及成千上万张图。如果 GPU 对每个材质球和网格都进行渲染,将会导致 GPU 负担重大,我们可以理解为一个材质球一个 drawcall 会导致 drawcall 过高。
drawcall:绘制调用,引擎向硬件发送渲染命令以绘制图形对象的过程。
UGUI 的优化
它将一部分相同类型的图片集合起来合成一张图,然后将拥有相同图片、相同着色器的材质球指向同一个材质球,并且把分散开的模型网格合并起来,这样就生成了几个大网格和几个不同图集的材质球,以及少许整张的图集。
图集:它把很多张图片放置在一张图集上,使得大量的图片和材质球不需要重复绘制,只要改变模型顶点上的 UV 和颜色即可。
UV:分别是图片在显示器水平、垂直方向上的坐标。
UGUI 系统并不是所有的网格和材质球都合并成一个,它只是把相同层级的元素,以及相同层级上的拥有相同的材质球参数的进行合并处理。
合并成一个网格,就相当于是一个静止的模型,如果移动了任何元素,或者销毁了任何元素,或者改变了任何元素的参数,原本合并的网格就不符合新的要求了,于是 UGUI 系统就会销毁这个网格,并重新构建一个。
我们要想方设法合并更多的元素,减少重构网格的次数,以达到更少的性能开销目的。
UGUI 系统的组件
1、Canvas 组件
画布,我们把各类元素放在画布上后,Canvas 要做的事情就是合并这些元素。
合并的规则:在同一个 Canvas 里,将相同层级、相同材质球的元素进行合并,从而减少 drawcall。
相同层级不是指 gameobject 上的节点层级,而是覆盖层级。
Canvas 的参数 Render Mode(渲染模式)
(1)Overlay 模式——不以 Camera 为基准
- 不与空间上的排序有任何关系,空间上的前后位置不再对元素起作用。
- 它常用在纯 UI 的区域内。
- Sort order 参数在排序时被重点用到,Sort order 参数的值越大,越靠前渲染。
(2)Screen Camera模式——以 Camera 为基准
- 相对比较通用一点,它依赖于 Camera 的平面透视,渲染时的布局依赖于它绑定的 Camera。
- 想让更多的非 UGUI 元素加入到 UI 中,Screen Camera 模式更加具有优势。
- 这种模式是实际项目中制作 UI 最常用的模式,不过 UGUI 系统底层针对排序有一些规定,如对 z 轴不为0的元素,会单独提取出来渲染,不参与合并。
(3)World Space 模式——以 3D 世界为基准
- 主要用于当 UI 物体放在 3D 世界中时,比如,一个大的场景中,需要将一张标志图放在一个石块头上。
- 与 Screen Camera 的区别是,它常在世界空间中与普通 3D 物体一同展示,依赖于截锥体透视(Perspective)Camera。
- 它的原理与普通物体一样,当 UI 物体在这个 Camera 视野中时,就相当于渲染了一个普通的 3D 图片,只是除了普通的渲染 Canvas 外,还对这些场景里的 UI 进行合并处理。
2、Canvas Scaler 组件
屏幕适配组件,用来指定画布中元素的比例大小。
-
Constant Pixel Size:简单指定比例大小。
-
Scale With Screen Size:以屏幕为基准的自动适配比例大小的规则。
-
Constant Physical Size:以物理大小为基准的适配规则。
在实际手游项目里,设备的屏幕分辨率变化比较大,通常使用以屏幕为基准的自动适配比例大小的 Scale With Screen Size 选项。
3、Graphic Raycaster 组件
输入系统的图形碰撞测试组件,它并不会检测 Canvas 以外的内容,检测的都是 Canvas 下的元素。
当图元素上存在有效的碰撞体时,Graphic Raycaster 组件会统一使用射线碰撞测试来检测碰撞的元素。也可以设置完全忽略输入的方式来彻底取消点击响应,还可以指定阻止对某些 layers 进行响应。
4、EventTrigger 组件
输入事件触发器,与此脚本绑定的 UI 物体都可以接收输入事件。它主要起到点击响应作用,配合 Graphic Raycaster 进行响应。
5、Image、RawImage 组件
这两个是 UI 里的主要部件,它们可以对图片进行展示,包括图片,图集。
两者的区别:Image 组件仅能展示图集中的图元,但展示的图元可以参与合并;而 RawImage 组件能展示单张图片,但无法参与合并。
通常我们会将小块的图片打包成图集来展示,这样更节省性能也更节省内存,这也是 UGUI 自动集成的功能,每个图片资源都有一个 tag 标记,标记决定了哪些元素会合并到同一张图集内,如果没有 tag 标记,则默认不会合并图集,它自己就是自己的图集。
不使用图集而使用 RawImage 展示单张图片的时,通常都是由于图片尺寸太大导致合并图集效率太低,或者相同类型的图片数量太多,导致合并图集后的图集太大,而实际在画面上需要展示的这种类型的图片又很少,图集方式反而浪费大量内存空间,因此使用 RawImage 逐一展示即可。
6、Mask、RectMask2D 组件
遮挡组件,可以将其子节点下矩形区域外的内容剔除,是滚动窗口中最常用的组件。
这两种方式的主要是在剔除的方法上有所区别,在实现效果上都是一样的,其中 Mask 使用顶点重构的方式剔除矩形区域外的部分,而 RectMask2D 则采用着色器的剔除方式,每个元素都有自己的材质球实例和实例参数。
Mask、RectMask2D 的剔除方式存疑,可以参考U3D:Mask和RectMask2D_unity mask和rectmask2d-CSDN博客,具体细节在后面源码分析的章节深入分析。
7、其他组件
其他大部分逻辑组件都是可以重写的,比如按钮组件 Button、切换组件 Toggle、滚动条组件 ScrollBar、滑动组件 Slider、下拉框组件 DropDown、视图组件 ScrollView,如果不想使用它们,觉得它们的功能不够用,也可以用 Image、Mask 等几个核心组件组合后重写。
实际工作中,很多项目都会自定义属于自己的组件。为什么要自定义呢?很多时候,项目里的需求是多样化的,若有自己的组件,在有特殊需求和特殊逻辑时,就能够毫不费劲的更改。所以,大部分项目中都会重写一些组件来用来给自己项目使用,也有一些人总结了这些组件的经验,编写了比较好用的组件开源在 Github 上。
原文地址:https://blog.csdn.net/renxi0/article/details/140684448
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!