2022-06-273272次浏览
1评论
35收藏
8点赞
分享
本文大部分内容是对2017 Epic Game的工程师郭春飚先生在 Unreal Open Day上演讲的进一步解释及实际案例分析,欢迎大家多多交流。
首先对UE4中UMG渲染结构进行简要介绍:
User Widget:对应一个用户界面。
Widget Tree:每一个 User Widget 都是存储成树状结构。
Panel Widget:不会渲染出来,用于对 Child Widget 进行布局,如 Canva Panel, Grid Panel, Horizontal Box 等。
Common Widget:用于渲染,会生成到最后的 Draw Elements 中,如 Button, Image, Text 等
在游戏渲染时,会遍历两遍widget tree,分别计算widget的尺寸和draw elements,draw elements是根据common widget的类型和参数生成的。一个user widget会生成1个或多个draw elements。
之前我们在UMG里面介绍过Visbility内不同设置代表的意思。
那么在渲染消耗上从小到大的顺序是 Collapsed<Hidden<Hit test invisible=Set hit test visible<Visible
由于visible状态可以接受交互事件,因此在收到交互事件的时候会遍历目前所有visible状态的UI控件,因此可见但不可交互的控件的visibility调成Set hit test visible会提高计算速度。
有许多控件的默认状态就是visible,例如image,因此在确认控件不接收交互事件时可以设为set hit test invisible可以减少不必要的开销。
在UI开发时,一个界面会用到多个资源来进行拼接。那么客户端在绘制这个页面时,会自动检索这个界面引用到的n个资源,需要计算n次。而如果恰好这n个资源都在一个合图里,则程序只需要读取一次合图文件即可完成这个页面的绘制,只需要计算1次。
Step1
将需要合图的资源用PS4合成一张合图。
Step2
Step3
右键目标Texture选择Extract Spirtes,将Texture炸开成单独资源。
Step4
改名,然后就可以在UMG中引用资源啦!
缺点:
可以发现这个过程较为繁琐,且迭代之后需要重新命名,很难在实际项目中运用。
方法二-Paper2d
Paper2d文件是UE4中一个基于sprite的系统,主要目的是用于制作2D网格游戏(如超级玛丽)和序列帧动画的,但是在功能上与合图有极强的相似性,因此可以借用paper2d来进行合图。
Step1
安装一个TexturGUIPacker,并选择UE-Paper2d框架。
Step2
将需要的资源拖入sprite列表中,注意Trim mode设为None,否则会自动裁切空白像素。
若资源量过大导致Maxsize 2048x2048 不够用的话,最多可以设为 4096x4096 ,因为UE4默认最大读取4K尺寸贴图。
Step3
点击Publish Sprite Sheet后自动生成一个paper2d文件,建议将tps(TextureGUIPacker工程)、paper2d、其他资源文件放在同一个目录下进行维护。
Step4
将paper2d文件拖入UE4自动生成Texture文件夹(合图文件)和Frames文件夹(拆分资源)。
Step5
后期资源修改时只需维护TPS文件,将新的paper2d导入UE4则可自动修改相关资源了。
Step6
为了避免PC端资源尺寸不够导致出现锯齿,可打开Project Setting>Editor>Paper2D-import将默认导入材质设为UI。
在目前的UI界面中,默认是在每一帧都对每一个UI控件进行渲染,但是有些时候UI并不是需要每一帧都进行渲染的,那么InvalidationBox的作用就是将这种UserWidget封装起来,从而缓存Slate Tick数据,不需要每帧都进行计算。只有他的某个child widget的渲染信息发生变化,才会通知Invalidation box更新缓存信息。
而当一个Invalidation Box内又存在一个需要实时更新的控件(如一个头像node,头像照片一般不需要每帧都渲染,而玩家又设置了一个需要实时渲染的动态头像框),则需要对该控件进行单独设置。
第二种处理UI不需要逐帧渲染的方式是Retainer Box,这个控件可以让他的子集每隔几帧渲染一次。
上面的这个例子,将一个User WIdget拆分成四部分,每三帧为一个循环,分别对不同的内容进行渲染。做法也是在外层嵌套Retainer Box,对Phasing项进行设置。
由于retainer box的phase count是全局性的,若出现如上图的两个设置,则在每15帧这两个retainer box会同时更新,导致帧数下降。Invalidation box内的retainer box是不生效的,若有需要则在retainer box内嵌套invalidation box。Retainer box会额外占用显存,因此也不是retainer box越多越好的。
Retainer Box还有一个额外的好处,就是可以为UMG添加蒙版。只需要将设置好的UI材质拖到这里,就可以为其子集添加蒙版效果。
注意:Rentainer Box的蒙版效果只有运行游戏之后才能看到。
大部分的 UI 优化工作(比如说 Invalidation Box, Retainer Box)都是在项目后期(UI 基本开发完成后)再进行的。UE4 提供了很丰富的功能和调试工具,熟练掌握这些功能能够帮助开发者实现高性能的UI。
评论 (1)