转自:https://blog.csdn.net/debugconsole/article/details/79281290

随着技术的不断升级,高性能的引擎逐渐受到越来越多研发商的青睐,UE4就是其中之一。在上周Unreal Open Day 2017活动会上,大宇就宣布旗下经典IP《仙剑奇侠传》、《轩辕剑》的续作,即《仙剑奇侠传7》和《轩辕剑7》将采用虚幻4引擎开发的消息。

而从另一方面,用虚幻4引擎制作游戏也需要注意一些问题。此前,葡萄君曾在《》一文中有所提及,近日,同样在Unreal Open Day 2017活动上,Epic Games的开发者支持工程师郭春飚以“如何在移动平台上做UE4的UI优化?”为主题,从四个方面对整个优化过程进行了描述。

以下为演讲实录:

大家好,我是Epic Games的开发者支持工程师郭春飚,今天给大家介绍的是在移动平台上面做UE4的UI优化,因为我们之前一直接到国内开发者的一些抱怨,他们觉得UI在手机上面开了以后性能下降的很快,今天就专门给大家介绍一下怎么用UE4在UI上面做优化,这是今天要讲的内容,首先会演示一个案例,接下来介绍怎么做优化,一块是游戏线程优化,一个是渲染线程优化,最后是编程技巧,先做案例介绍。

案例介绍

这是我们的一个演示工程,这个工程大概是我们做的测试工程,是在手机上面演示的,我们测试的机器是小米4C,同时开启了Mobile HDR。

谈性能之前先看一下性能指标,不要使用Stat.Slate会影响开发者做性能分析,可以使用stat dumpave num查看LOG,性能指标可以做Slate Tick - STAT_SlateTickTime游戏线程:Vertex Buffer;Slate Render - STAT_SlateRenderingRTTime渲染线程:UI渲染到Back Buffer;Widget Render - FWidgetRenderer_DrawWindow渲染线程:UI RTT / Retainer Box。

这是小米4C的性能数据,一开始是FPS是36,右边的列表是我们的优化开关,大家看到这个优化效果,一开始游戏线程11毫秒,渲染线程是8毫秒,用了Invalidation Box以后,游戏线程就减少到了1毫秒,这时候FPS提升不大,因为在手机上面UI的瓶颈更多是GDO,然后如果打开了Retainer Box以后,我们的渲染线程大概能减低3毫秒,这个时候FPS提高将近10每帧。

游戏线程优化

接下来就开始介绍具体的优化方案,第一步是游戏线程优化,这是一个小的事例,这个UI上面有两个贴图和一个文本框,Invalidation Box,每帧操作Grid Panel遍历所有的Child Widgets,Image1, Text1, Image2分别计算Draw Elements,Grid Panel将Image1和Image2的Draw Elements合并,最后Grid Panel返回2个Draw Elements进行渲染,如果是像这样一个复杂的控键数,这个开销也是比较大的。

我们Invalidation Box缓存Draw Elements (Vertex Buffer),用Invalidation Box封装Grid Panel。

这个有一点需要注意的是一个Volatile的概念,如果标志成Volatile的Widget每帧都会重新计算,一些属性的Widget Binding会使得Widget变成Volatile,Check Box放在Invalidation Box下会不起作用,需要设置成Volatile,建议自定义User Widget,用Button实现对应功能。

这就是引擎提供这样一个工具,叫InvalidationDebugging,开发者可以使用Slate.InvalidationDebugging找出Volatile,另外可以使用Slate.AlwaysInvalidate测试是否会突然卡顿。

有一个注意的是Invalidation Box自身会被标志成Volatile,一些重复使用的子控件建议不要Invalidation Box, 会有额外计算,Invalidation Box放在Retainer Box的下层。

接下来要讲一下可见性,除了可否可见以外还有是否可以接收点击测试,HitTestInvisible 可见、当前控件不可点击、所有子控件不可点击,SelfHitTestInvisible 可见、当前控件不可点击、不影响子控件,Hidden 不可见、占用布局空间,Collapsed 不可见、不占用布局空间。

如果大量的Visible会导致点击响应太慢,这个也会消耗很大的性能,Button设置成Visible,其它Widgets可以设置成Self Hit Test Invisible或Hit Test Invisible,Collapsed不占用布局空间, 略优于Hidden,Show/Collapse要优于AddToViewport/RemoveFromViewport。

这里还要讲一个是Widget Binding,某些属性上Widget Binding会导致对应Widget被放入Volatile List,这些属性发生变化,表示对应的控件需要重新计算Vertex Buffer,所以我们尽量避免这个Widget Binding。另外还有一点是Widget Binding会每帧Tick执行,这一点也会带来比较大的性能开销,所以手机上面建议使用C++ Event设置Widget属性。

目前UE4的UI开发对于C++是很好的,右边的编辑器里面进行了UI界面,不建议把复杂的逻辑放在蓝图Tick中执行,在C++中声明变量, 引擎会自动绑定编辑器中的Widget。

渲染线程优化

接下来介绍一下渲染线程优化,渲染线程首先介绍一个合并批次,我们在左图看到的是UI的有些可以合并批次,有些不可以合并批次,像不合并批次Canvas Panel、合并批次Grid Panel、Uniform Grid Panel、Vertical Box、Horizontal Box。

另外对于UI方面,我们可以使用Stat Slate查看批次,Num Batches,尽量使用可以批次的UI容器,但不用刻意追求合并批次。通过Sprite实现合并贴图功能。

接下来介绍一下UE4怎么合并贴图,这是我们合并贴图和贴完以后的情况,这是像素填充率,这里是背包界面的前5个Draw Call,后4个Draw Call的渲染面积很大,已经接近第一个背景图,可以看到UI的像素填充率非常高,这个时候我有接近5倍的面积,这个时候也有将近约5倍的Pixel Shader的执行次数,所以我们要提高像素填充率。

Retainer Box,将UI渲染到Render Target,再将Render Target 渲染到屏幕,另外引擎处理了点击响应区域的映射,鼠标点击区域引擎已经自动在屏幕上面映射了相应的测试。

Widget Render:将UI渲染到Render Target,Slate Render: 使用缓存的Render Target渲染Back Buffer,每隔3帧一个循环进行Retainer Box的更新,将1帧的UI渲染工作量分配到3帧去处理。

性能对比方面,关闭Retainer Box 7.7ms+0ms,开启Retainer Box是1.5ms+3.2ms,FPS提升由38到48。

Retainer Box 会占用额外的显存,因此建议仅在主界面上使用;Retainer Box区域尽量小,提高渲染效率、降低显存使用;Retainer Box会为每个User Widget实例创建一个Render Target, 因此重复使用的User Widget不要使用Retainer Box;游戏线程的Tick也会相应的隔几帧执行一次;持续表示的效果可以从Retainer Box中分离出来,但需要注意像素填充率;也可以从特效设计的方面解决;Invalidation Box放置在Retainer Box上方没有意义;推荐一个Retainer Box下跟一个Invalidation Box的方式;Retainer Box可以上材质效果。

另外需要注意的是,每隔3帧更新一次Retainer Box A,在第0帧更新;每隔5帧更新一次Retainer Box B,在第2帧更新;每隔15帧这两个Retainer Box就会同时更新,这样帧数变得不太稳定,导致帧数下降比较多,Phase Count的设置要全局考虑,避免重叠而导致帧数不稳定,所以必须做很好的控制。

Invalidation Box我们是每帧更新一次,但是我们很多时候可以做到根据事件触发,比如说背包穿戴了一个装备、卸下一个装备,按钮发生变化等等,这个时候可以根据事件更新,甚至不用每几帧更新一次,这样的话可能我们的UI交互不是很频繁,它的提升可能还是比较大的。

这就是我们的一个演示,如果打开了事件驱动的Retainer Box时,可以看到RTT的时间从3毫秒降低到0,最后可以看到我们这样一个复杂的界面,我们的游戏线程只花了1毫秒,渲染线程也花了1点多毫秒在小米4C上,而UE4是一个多线程渲染的,所以可能时间大概有11毫秒左右,当然事件驱动的Retainer Box刚才也说过了,对于频繁使用的UI不建议使用,所以可能最后需要看的是我们有多少频繁交互的事件,当然对于低端机的话带来很大的性能提升,如果我们有UI特效,可能在这个上面这种事件驱动没有办法更新,所以我们比较适合推荐这种方式在低端手机开启,首先关闭了UI特效。

这也是开发者比较关心的功能,左图有简单的材质,右图可以自动关闭材质和切换到低材质,这样可以兼顾高端机的效果和低端机的性能,DYNAMIC_MULTICAST的框架,这样程序可以变得更容易维护,开发也比较简单。

编程技巧

最后介绍UI方面的编程技巧,当然蓝图的话其实在大多数情况下性能都是没有问题的,但是如果我们要在低端机上面需要追求很好性能的话,其中有计算量比较大的逻辑,我们是不建议放在蓝图里面做,因为毕竟中间有很多的分装,建议可以把一些计算量比较复杂的逻辑下放在C++里面做,运行效率比蓝图高,更灵活,很多C++接口并未开放成蓝图接口,除了UI动画,其它代码都能用C++实现。

对于UI开发,我们建议开发者有Widget Manager,可以在蓝图中,也可以在C++中,就是管理所有User Widget,Brush、Font等资源也可以在Widget Manager中统一管理,这样的项目比较好管理,特别是UI比较多的时候。

接下来介绍一个怎么在UE4当中释放贴图内存,某些UI的贴图较大,这个时候应用程序希望可以在关闭UI后,释放对应贴图,这个时候要做一些简单的扩展,将UI贴图控件自定义成弱引用,管本这个UI空间以后这个内存就会释放掉。

UE4因为用GC回收内存,开发者并不是马上知道哪一块内存马上释放了,这个时候可以看到贴图还有哪些地方在引用,保证引用技术都是零,这个时候后面的GC可以释放它,可能一些图片被不知名的地方还在引用着。

这里还有一个小技巧3DRTT,这个小技巧并不需要每帧Tick,只要和动画频率大致同步就可以,所以我们要把每帧去渲染的两个选项关闭,同时这个蓝图我们设置成0.03秒Tick一次,产生在蓝图当中Tick这样的RTT,另外还有一个小细节就是Render Target的尺寸不要太大,会影响显存和渲染效率。

最后总结一下今天的技术点还有优先级,因为有些项目已经在开发中或者已经在后期,这个时候遇到UI导致的性能问题可以根据这个优先级做测试,前面讲到这些比较重要,包括下面合并批次容器,只要把这些设计好,我们移动项目的UI基本上不会有什么瓶颈了。

Epic Games工程师分享:如何在移动平台上做UE4的UI优化?的更多相关文章

  1. 宣布与Epic Games合作,为虚幻引擎创造Cesium

    Cesium中文网:http://cesiumcn.org/ | 国内快速访问:http://cesium.coinidea.com/ 没有什么能比支持史诗游戏和史诗巨无霸计划(Epic MegaGr ...

  2. 阿里资深工程师分享支付宝热补丁技术—— AndFix原理

    本文由嵌入式企鹅圈原创团队成员.阿里资深工程师Hao分享. 上次我们介绍了用dexposed方案实施热补丁的原理,它本质上就是hook要修改的函数,这样一来在正式版本发布时就不能直接拿热补丁的代码集成 ...

  3. GDC2016 Epic Games【Bullet Train】 新风格的VR-FPS的制作方法

    追求“舒适”和“快感”的VR游戏设计方法   http://game.watch.impress.co.jp/docs/news/20160318_749016.html     [Bullet Tr ...

  4. Linux平台上DPDK入门指南

    1. 简介 本文档包含DPDK软件安装和配置的相关说明.旨在帮助用户快速启动和运行软件.文档主要描述了在Linux环境下编译和 运行DPDK应用程序,但是文档并不深入DPDK的具体实现细节. 1.1. ...

  5. .NET平台上的Memcached客户端介绍

    早上接到一个任务,需要对Linux服务器的Memcached的update操作进行性能测试,我发现我是一个典型的“手里拿着锤子, 就把所有问题都当成钉子”的人.我第一个念头就是,上Memcached的 ...

  6. 分享:在微信公众平台做HTML5游戏经验谈(转载与http://software.intel.com/zh-cn/blogs/2013/04/03/html5)

    分享:在微信公众平台做HTML5游戏经验谈 Dawei Cheng 程大伟... 于 星期三, 03/04/2013 - 03:19 提交 最近微信公众游戏平台讨论得如火如荼,大有HTML5游戏即将引 ...

  7. .NET平台上的Memcached客户端介绍(Memcached Providers)

    早上接到一个任务,需要对Linux服务器的Memcached的update操作进行性能测试,我发现我是一个典型的“手里拿着锤子,就把所有问题都当成钉子”的人.我第一个念头就是,上Memcached的官 ...

  8. 在不同平台上CocosDenshion所支持的音频格式

    在大多数平台上,cocos2d-x调用不同的SDK API来播放背景音乐和音效.CocosDenshion在同一时间只能播放一首背景音乐,但是能同时播放多个音效. 背景音乐 Platform supp ...

  9. 运行在TQ2440开发板上以及X86平台上的linux内核编译

    一.运行在TQ2440开发板上的linux内核编译 1.获取源码并解压 直接使用天嵌移植好的“linux-2.6.30.4_20100531.tar.bz2”源码包. 解压(天嵌默认解压到/opt/E ...

随机推荐

  1. java.lang.NoClassDefFoundError: org/apache/commons/logging/LogFactory解决方案

    导入commons-logging-1.2.jar辅助类包即可. 报错提示: Exception in thread "main" java.lang.NoClassDefFoun ...

  2. pycharm 的操作1

  3. The Microservices Workflow Automation Cheat Sheet

    Written by Bernd Rücker on Dec 12 2018 in the Best Practices category. Editor’s Note: This post orig ...

  4. Creating Node.js Command Line Utilities to Improve Your Workflow

    转自:https://developer.telerik.com/featured/creating-node-js-command-line-utilities-improve-workflow/ ...

  5. DevExpress的DateEdit控件正确显示日期的周名称

    DevExpress 的控件相当好看而且很好用,但 DateEdit 在是显示周名时,只能显示一个“星”字. 以下是解决方法,此解决方法不需修改其源码,所以免去了重新编译的必要,可直接使用其发布的标准 ...

  6. 适配器(Adapter)

    Adapter:将一个Class的接口转换成另一个Class的接口,使原本因接口不兼容而不能合作的Class可以一起运作.主要有两种:迭代器适配器(Iterator Adpater)和容器适配器(Co ...

  7. MySQL 出现 Host is blocked because of many connection errors; unblock with 'mysqladmin flush-hosts'

    MySQL 出现 Host is blocked because of many connection errors; unblock with 'mysqladmin flush-hosts' 一大 ...

  8. Java参数验证Bean Validation 框架

    1.为什么要做参数校验? 参数校验和业务逻辑代码分离,参数校验代码复用,统一参数校验方式.校验不太通过时统一异常描述. 2.bean validation规范 JSR303 规范(Bean Valid ...

  9. 代理模式proxy

    代理模式的共同优点如下: (1) 能够协调调用者和被调用者,在一定程度上降低了系统的耦合度. (2) 客户端可以针对抽象主题角色进行编程,增加和更换代理类无须修改源代码,符合开闭原则,系统具有较好的灵 ...

  10. base64 base64urlsafe

    1. base64 不算是加密算法,只能说是一种转码.使用64 个可见的字符来代替 ASCII码 中的256 个字符. 2. ASCII码占用一个字节,可以有0-255共256个取值.前128个为常用 ...