UE4入门之路(UI篇):UI性能优化

云鹏童鞋

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内不同设置代表的意思。

  • Visible                    可见并接受交互事件
  • Collapsed              不可见且不占用任何体积
  • Hidden                   不可见但占用体积,不接收交互事件
  • Hit test invisible     可见,且他和他的子节点都不接受点击事件   
  • Set hit test visible  可见,且他自身不接受点击事件,不影响子节点

那么在渲染消耗上从小到大的顺序是  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

将合图导入UE4生成一个texture,双击资源进行设置,将Compression Setting设为UserInterFace2D,texture group设为UI。
UI的Texture设置

Step3

右键目标Texture选择Extract Spirtes,将Texture炸开成单独资源。

将合图转化为单独资源

Step4

改名,然后就可以在UMG中引用资源啦!

缺点:

可以发现这个过程较为繁琐,且迭代之后需要重新命名,很难在实际项目中运用。

方法二-Paper2d

Paper2d文件是UE4中一个基于sprite的系统,主要目的是用于制作2D网格游戏(如超级玛丽)和序列帧动画的,但是在功能上与合图有极强的相似性,因此可以借用paper2d来进行合图。

Step1

安装一个TexturGUIPacker,并选择UE-Paper2d框架。

Step2

将需要的资源拖入sprite列表中,注意Trim mode设为None,否则会自动裁切空白像素。

TextureGUIPacker

若资源量过大导致Maxsize 2048x2048 不够用的话,最多可以设为 4096x4096 ,因为UE4默认最大读取4K尺寸贴图。

Step3 

点击Publish Sprite Sheet后自动生成一个paper2d文件,建议将tps(TextureGUIPacker工程)、paper2d、其他资源文件放在同一个目录下进行维护。

资源、合图、paper2d及TPS工程

Step4

将paper2d文件拖入UE4自动生成Texture文件夹(合图文件)和Frames文件夹(拆分资源)。

刚刚制作的paper2d导入后自动生成的文件

Step5

后期资源修改时只需维护TPS文件,将新的paper2d导入UE4则可自动修改相关资源了。

如果有资源修改未生效,保存后选择资源进行Reload

Step6

为了避免PC端资源尺寸不够导致出现锯齿,可打开Project Setting>Editor>Paper2D-import将默认导入材质设为UI。

Invalidation Box

在目前的UI界面中,默认是在每一帧都对每一个UI控件进行渲染,但是有些时候UI并不是需要每一帧都进行渲染的,那么InvalidationBox的作用就是将这种UserWidget封装起来,从而缓存Slate Tick数据,不需要每帧都进行计算。只有他的某个child widget的渲染信息发生变化,才会通知Invalidation box更新缓存信息。

在外层嵌套Invalidation Box

而当一个Invalidation Box内又存在一个需要实时更新的控件(如一个头像node,头像照片一般不需要每帧都渲染,而玩家又设置了一个需要实时渲染的动态头像框),则需要对该控件进行单独设置。

勾选 is Volatile可以使其不受InvalidationBox的影响

Retainer Box

第二种处理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 添加材质后效果

注意:Rentainer Box的蒙版效果只有运行游戏之后才能看到。

总结

大部分的 UI 优化工作(比如说 Invalidation Box, Retainer Box)都是在项目后期(UI 基本开发完成后)再进行的。UE4 提供了很丰富的功能和调试工具,熟练掌握这些功能能够帮助开发者实现高性能的UI。

评论 (1)

0/1000
网易游学APP
为热爱赋能
扫描二维码下载APP