深入UGUI Mask组件原理和性能深度优化
对于一款游戏UI系统必不可少,UGUI是现在项目组中实现UI系统的大多数解决方案,使用广泛。UGUI提供的组件很多,外部很多厂商也提供了很多UGUI的第三方插件,而客户端开发人员往往过度关注项目进度实现功能,对各个组件仅仅停留在“会使用”这个基本层面上,并没有对组件本身的实现原理、优缺点以及性能方面做深入了解。
该课程以性能备受争论的Mask组件为例,从Mask组件的实现原理入手,深入到CPU、GPU和GC上Mask产生的影响,然后给出解决方案,最后给出在UI上使用3D模型,如何使用Mask原理对其进行遮罩处理。
1. Mask组件实现原理以及存在的问题
2. Mask组件的性能以及优化(CPU、GPU、GC)
3. 如何用Mask组件来给3D Object做遮罩
作者于洋,Unity技术专家、引擎组组长。曾就职于人人网、Kabam、竞技世界。从事游戏开发十余年,经历了从Flash到Unity的游戏开发过程,长期从事游戏渲染和性能优化相关工作,对PBR、云、雾、地形、URP管线等有深入研究,曾参与过《Legacy of Zeus》、《荒岛求生》、《mythwar puzzle》等游戏的渲染和性能优化工作,乐于分享渲染和优化的相关技术。
目录
1|概述
2|Mask组件实现原理以及存在的问题
3|Mask组件的性能以及优化
4|如何用Mask组件来给3D Object做遮罩
5|结论
1|概述
遮罩不是一种可见的UI控件,而是一种修改控件子元素外观的方法。遮罩将子元素限制(即“掩盖”)为父元素的形状。因此,如果子项比父项大,则子项仅包含在父项以内的部分才可见。
拥有Mask组件的UI控件,可以限制其子对象的显示范围,即当子对象的显示范围明显大于父对象的显示范围时,游戏视图就只显示父对象范围内的子对象,其他部分自动隐藏。
我们在Canvas下面新建一个2D UI Image,选择一个带有形状图案的Sprite,在该物体上Add Mask Component,这样,它就变成了一个遮罩物体。以该物体作为父对象,在其下面新建一个2D UI Image作为子物体,选择一个Sprite,这样就完成了一个简单的Mask组件的使用,结果如下图:
意思就是是否绘制出Mask组件上的Image图形,如下图:
勾掉后,就不会再绘制出该Image,具体有关的性能问题,在后续会详细讨论。
以上基本介绍了一下UGUI Mask组件以及最基础的使用方法,在使用方法上,大家作为Unity的开发人员肯定是特别熟悉。
但是在实际游戏开发中,我们不仅仅要关注于项目的功能开发进度,如果游戏的性能不能满足要求,经常出现卡顿、闪退等问题,用户体验严重下降,就算开发出再好的游戏玩法也没办法满足玩家的体验需求。
性能优化是游戏项目开发中一个重要且必须的元素。而即便在硬件设备高速发展的今天,随着用户和项目的需求的持续增长,对游戏特效、画质、高度复杂且真实的场景的需求也在逐渐榨干硬件性能,无论大公司还是小公司,无论研发团队有多么丰富的开发经验,性能优化这件事永远是一个非常棘手而又无法绕开的问题。
那么我们在进行游戏开发的时候,对项目中所使用到的组件、库、插件、Unity built-in的功能的过程当中,要时刻警惕其性能问题:有没有给项目带来严重的性能下降?如果出现了性能下降了,是由于使用了哪个功能导致的?有没有其他的方案可以作为替代?
Mask组件就是其中之一,我们在使用的时候要不断地进行性能评估。
你是否在实际开发中有过下面几个疑问:
1.在使用了Mask组件之后,DrawCall为何增加特别严重?这些DrawCall的来源是哪里?
2.使用Mask组件做遮罩的视觉效果其实并不理想,有锯齿?
3.网上说的使用Mask组件的子对象没办法和外界做合批处理,低层的原因是为什么?
4.如何对Mask组件进行优化以满足自己项目的性能要求?
接下来的章节会一一详细解答这些问题。
读完全篇后你会深入了解UGUI源代码和实现逻辑,并掌握Mask组件对模板缓冲区的使用。