观察 | 硬干货!《球球大作战》优化升级之路

2019-05-16 21:50

| DrawCall从913降到83。

5月10日至5月12日,由Unity主办的Unite Shanghai 2019在上海国际会议中心召开,作为行业内顶尖的开发者大会,Unity邀请了业内各领域的技术专家来到现场为开发者分享最新技术和制作经验。

会上,巨人网络《球球大作战》客户端主程 王国祎 和资深技术 徐宇峰 以“《球球大作战》优化之路”为题,与现场开发者围绕游戏在优化过程中遇到的难题与解决方案,展开了一次深度的技术分享。

本次分享主要拆分为Unity2017的版本选择与基础优化、运用新特性优化游戏性能、RenderTexture实战技巧三个部分,其中囊括了《球球大作战》在优化过程中的多种解决方案,为开发者展示了一种新颖的渲染性能优化思路。

以下为手游那点事整理的演讲内容:

大家好,感谢大家来听我们的分享。我是《球球大作战》客户端负责人 王国祎,之前都是以听众的角度参加大会,这次作为一个演讲嘉宾过来参加,感觉过程还是很奇妙的。

简单介绍一下球球这个游戏,《球球大作战》是一款多人休闲竞技游戏,主要强调多人合作玩法。游戏发布于2015年,当时很多玩游戏的小朋友现在都上了初中和高中。就像超级马里奥和魂斗罗成为我们这一代人的回忆一样,我也希望球球能成为他们的长久陪伴。

下面进入本次分享的第一部分,其中包括我们在升级Unity2017过程中遇到的难点和解决办法。在此之前,我要先介绍一下为什么选择Unity2017。

1.Unity2017的版本选择与基础优化

对于选择Unity2017这个引擎版本,以及《球球大作战》在游戏性能上的提升,我们主要考量到8个方面。

1.ASTC图片压缩格式:我们尝试过全平台贴图使用这个格式,后来经过大量测试发现Android不支持这个格式的机型占比很高,最后正式版本上只在iOS上使用ASTC格式。

需要注意的是,iOS在iPhone 5s及以下机型硬件不支持这个贴图压缩格式,贴图解压会变成RGBA格式。

2.Bundle LZ4压缩: Unity2017的Bundle LZ4压缩方式测试下来,解压速度比之前lzma方式快很多,内存消耗也更合理。

3.Bundle文件支持异步加载和读取资源。

4.运行时设置屏幕分辨率:这个方法测试下来可以很好地达到提高帧率的效果,在Unity4.7版本上,设置屏幕分辨率会出现闪一次黑屏现象,而Unity2017版本解决了这个问题。我们可以通过动态调节分辨率,达到提高帧率的目的。

5.Camera RT调节分辨率:在Unity2017上也是一种提高帧率的方式。

6.Android支持IL2CPP。

7.支持GPU Instance。

8.动画系统可以对指定区域缩放,方便动画制作。

但在引擎升级过程中,我们也遇到了一些棘手的问题。比如性能在中档以下的大部分手机型号,渲染同样内容的帧率比旧引擎降低了10帧左右。

为此我们开发了一个只有核心玩法的版本,这个版本剥离游戏以外的系统,只有核心玩法。目的是加快测试进程和减少其他功能的影响。

最后,我们发现问题出在了一些设置的选择上。一个是Android上面的Blit Type,这是在Unity2017.2.x版本之后开放的,关闭选项后发现帧率确实提升了很多,总体提升在5到6帧。

另一个是Camera上的HDR,MSAA同时也去掉。由于游戏内没有使用实时光,去掉了Lighting里面的Realtime lighting,Mixed Lighting。修改后帧率基本上和旧引擎版本帧率一致。

除了帧率降低之外,引擎升级还出现了很多资源显示异常、资源丢失、错位等情况。

在资源升级时,部分资源会出现显示问题。有些情况是转换之前fbx文件中模型文件使用中文字符命名的,转化之后就会出现引用丢失的情况。这是mate文件中Unicode转换问题,需要对比旧meta文件来替换名称。

还有转化之后粒子缩放默认变成了Hierachy模式,皮肤缩放之后,出现显示问题。解决方式是转换成Local模式,配合缩放脚本,达到和之前一样的效果。

最后则是Asset Bundle打包时间变成,以及Andriod和iOS打包流程变更的问题。

我们对引擎升级的其中一个考量点是优化打包时间,球球美术工程现在有6G多,在用旧引擎打包耗时非常长,而且工程启动也非常慢。

升级Unity2017之后在打包速度和工程开启速度上都有些提升,同时我们把一些不频繁改动的旧资源拆解到另外一个工程里面,保证两个工程的引用是统一的、guid一致。这样每次只打包有差异的新资源,明显提升了打包时间。

在Android Studio打包时如果工程包含大量文件时打包会失败,问题出现在缓存大小上,默认是1024M.可以根据内存做一个适当调整。

导出 XCode 工程时 Framework Search Paths 会被清空,需要在导出时使用PBXProject.SetBuildProperty 方法添加丢失的库文件。

在新引擎对外测试时。我们想尽量让玩家来比较这两个引擎版本客户端,新的引擎我们打包成一个预览版,这个预览版的账号和正式服是共用的。让玩家在同一台手机体验两个版本,比较差异,提交反馈意见。

在开发时,我们始终存在两个版本,一个是原引擎工程版本,一个是Unity2017的引擎工程版本,内容和功能在原引擎版本上开发,再合并到Unity2017引擎版本上,并且同步更新出去。

为了不影响线上玩家,这两个版本会有一个兼容期,差不多在二个月。

2.运用引擎的新特性优化游戏性能

第二部分介绍下球球现有的优化。前面我们说的都是升级新引擎,升级的目的是为了使用新引擎所带的新特性,以前我们的优化很多都是从技术角度来处理问题。

比如,我们以为网络问题就是把TCP换成UDP就会缓解,以为渲染卡顿就是把DrawCall降低后就会减轻。最后,我们发现优化是多方面的,而且要从玩家的角度去改善体验。

有一次,我参加《球球大作战》的见面会,一个玩家说连他自己家WIFI时延时很高,就上网查原因,帖子底下有人说把wifi路由器的UDP防火墙关掉就会好,他尝试了下发现真的好很多。

这件事反应一个问题,之前我们的优化重心是自身的机房网络,游戏的网络底层,但其实问题更多的是连接玩家手机最后一公里的网络环境。

在美术标准制作上,我们之前都是按统一标准制作,而现在的标准则是由多个档位决定的。同时对应游戏中的价值,皮肤道具也是分一些正常道具,较炫酷的道具。我们把档位精细定位,规定好每个档位的皮肤指标,让资源划分更合理。

球球的LOD处理并不像3D场景的LOD切换高低配模型资源来实现的。

球球通过皮肤资源占比屏幕像素比例,进行高低品质资源的切换,主角本身皮肤和其他玩家的皮肤我们的LOD比例用了两套标准。LOD低配资源是提前渲好的一张贴图,优化后在比例很小的时候两者几乎看不出差别。

对于机型划分,早期尝试的方案是按手机cpu型号分类,后期测试时发现一些弊端,比如有些手机cpu处于中档性能,但同时屏幕分辨率也非常的高,那么总体的渲染表现就会降低。

优化后的方案,是根据游戏内玩家每局游戏的FPS曲线值,进行手机性能分类,这样也更符合游戏的真实卡顿表现。这个方案测试下来还是比较准确的。

我们会发现周边的同事都在不停的换新款的iphone,或者Android高端机,会习惯认为玩家的手机性能在变高。而实际上,通过游戏数据发现千元机占了我们60%多的用户,这也让我们把优化重点放在这些手机型号上。

针对游戏的网络监控,每局游戏结束后我们都会上报卡顿日志和网络日志,来统计每局游戏的卡顿情况。日志包括ping值变化,玩家网络环境测试,局内的卡顿信息,接下来会对这些数据进行整理和排查来寻找更多影响玩家的网络问题。

3.在实战中通过RenderTexture解决性能问题

大家好,我叫徐宇峰,负责《球球大作战》性能优化。

《球球大作战》为了吸引如此庞大的玩家群体,我们提供给玩家更炫更酷的皮肤,这些美轮美奂的皮肤,让《球球大作战》的游戏画面更加绚丽多彩,但随着皮肤日益精致,性能问题开始突出。

我们的皮肤正面看起来很简单,但从侧面看,皮肤由精美模型与很多特效组合而成,皮肤的材质大部分为半透明,大量的半透明材质无法合批渲染,导致单套皮肤DrawCall达到82个,面数1.1万,骨骼40个。

《球球大作战》最核心技能就是分身吃球,而当玩家分身之后,DrawCall更是暴涨,游戏中玩家最大16分身时,DrawCall有820多,面数达17.7万。

而在实际游戏中,多玩家多皮肤分身后,DrawCall经常能轻松过千。这是我们内部的极限测试版视频,大家能看到DrawCall最低有4、5百,最高达到2500多。如此高的DrawCall导致游戏帧率急剧下降、卡顿严重,而作为一款竞技游戏,性能与体验至关重要。

我们团队采用各种优化方法:

模型贴图合并:模型与贴图尽可能的合并在一起,利用Unity的动态合批渲染,减少DrawCall;

减少半透明材质:半透明会带来融合运算,其次重叠的半透明物体无法合批渲染,导致DrawCall增加;

减少粒子系统:粒子会增加CPU运算,还会增加DrawCall,每套皮肤的粒子数量我们控制在40以内;

LOD系统:上文已提到过;

降低分辨率:皮肤的贴图采用512分辨率,部分贴图在低端机器上降低到256k。

下面看看优化对比:

左右是一个LOD系统的效果对比,左边是高性能机型高画质,右边是低端机型流畅画质。左右相互对比可以看到,右边的皮肤少了些特效与动画,贴图分辨率也相应降低。

大家可能会觉得右边的皮肤有些模糊,因为目前是超大屏显示,在实际的主流6寸屏手机上,模糊不会很明显。通过以上优化,游戏性能大约提升52%。

但画面品质同样遭受损失,在中低端机器上尤为明显,这点很容易引起玩家的不满,美术团队也希望所有机型、画面尽可能的完美,并且过少DrawCall极大限制了美术的高水平发挥。

优化难点是皮肤分身后DrawCall暴涨的问题,我们想到用RenderTexture来降低DrawCall峰值,但皮肤有太多半透明。

渲染管线中,对于透明相关的处理是在管线后期进行的。由于不同物体是按照顺序渲染的,对透明的处理方式是混合,实际上就是shader输出颜色与此像素位置已有颜色的合并过程。

图上的混合公式就是Unity中最标准的混融模式Blend SrcAlpha OneMinusSrcAlpha假设将Camera背景的颜色设置为全黑色(0001)或全白色(1111) ,分别进行渲染。

设渲染后的颜色分别为Cblack、Cwhite,得到公式1和2,公式中蓝色为已知数,紫色为未知数,2个公式可以求出2位未知数,具体代码请参考右下角连接。

下面看看具体制作流程。

我们把原资源用单相机渲染到RenderTexture,相机每帧切换黑白背景,形成连续序列帧。之所以这样是单个相机能节省更多的DrawCall,但如果动画速度过快,就得用双相机保证品质。

RT经过GPU做算法剔除,输出到多张RenderTexture,这里RT我们采用512分辨率,一共40张,格式为ARGBHalf,真机占用内存约为20兆。

目前市面上主流手机内存大部分为2GB以上,所以内存很充足,但具体用到那种分辨率与RT数量的多少,需要根据不同机型做适当调整。

多张带透明RenderTexture组成序列帧,利用Plane切换RT做成序列帧动画,这里的序列帧会循环渲染,从RT1渲染到40,再回到第一张,Plane读取RT时也是循环读取,最后序列帧动画放到场景中与半透明背景、半透明皮肤以及UI等进行融合。

下面我们来看看原资源与RT资源的实时效果对比。

这是原素材与RenderTexture的实时效果对比,原素材由十几层特效叠加,而RenderTexture只有单个面。

大家看看不同资源的效果对比,新技术首先必须保证美术品质才能投入使用。


在美术品质保证后,再看看优化前后DrawCall对比,当分身不断增加时,DrawCall以线性增长。

大家可以看看右上角Batch数量,从最开始63暴涨至900多,优化模式下,分身的增加带来DrawCall的个位数增加,同时我们可以看到RT模式下,利用多张RenderTexture,每个分身的动画帧是错开的,动画并不完全一样。

我们再看看真机数据对比,测试平台为普通千元机。先看第一张图,分身数从1至16,普通模式DrawCall从63暴涨至917翻了14.5倍,每一次分身数量的翻倍都让DrawCall剧烈变化。

而RT模式从64到83只增加19个,再看后面CPU消耗图,在RT模式下,CPU的消耗非常平稳,而普通模式最大分身时消耗已经翻倍。

再来看看FPS与内存消耗,FPS在普通模式下16分身帧率已经降低到25,加上UI与其他逻辑消耗,已经产生卡顿。

而RT模式帧率非常平稳,内存方面因为RT用了40张16位的512贴图,内存大约多20mb,这是RT模式唯一消耗点。实际应用中我们会根据机器的内存容量,控制RT的数量与分辨率。

《球球大作战》同屏有上千物体,每帧数千个物体的位置,大小,动画,网络数据等伴随着产生大量逻辑运算,主要逻辑有:

1.利用插值函数使物体的移动更加平滑;

2.玩家吃球后重量会增加,根据重量来计算球的尺寸与前后位置,尺寸越大物体越靠近摄像机;

3.AI状态机,玩家根据游戏状态,如2玩家距离接近时,会播放调侃动画,吃掉其他玩家时播放炫耀动画;

4.相机视野计算,玩家所有球的数量与尺寸变化,都伴随着相机位置与FOV调整,每个分身必须在相机视野内,最大分身尽可能处于屏幕中心;

其他还有网络数据解压缩、解密、背景迷雾、UI运算等,以上这么多的实时运算量会对CPU产生巨大压力。

我们利用Unity2018的ECS系统,把所有逻辑做分类,纯逻辑运算做成PureECS,其他部分做成HybridECS,数千物体的逻辑运算,尽可能分配到多个核心。这极大的提升游戏性能,并且更快更复杂的运算让物体的移动、旋转更加平滑和细腻,增强游戏的用户体验。

上述的优化方法,部分处于《球球大作战》的试用阶段,我们一直都在不断尝试、开拓创新,使用各种优化措施,让《球球大作战》拥有更好的用户体验,并不断焕发新的活力。

我的演讲到此结束,谢谢大家!

附现场采访内容:

1.在io游戏的画面处理上,有什么细节是开发者需要注意的?

王国祎:首先io游戏属于多人竞技品类,这个类型操作体验非常重要,比如球球是限制在60帧运行的。如果把游戏限到50帧,虽然只少了10帧,但是实际手感的差别会很明显。

另外,如何准确表现角色的大小,也是容易被忽视的点。比如一些3D的游戏,角色脚底会有一个表现范围的圈,因为只靠角色模型会很难表现影响范围。而球球现在皮肤也是越来越炫,不只是一个简单的球体,模型上承载的东西非常多。

因此在制作过程中,包括美术和策划都会强调一点,就是真实球体的范围,不能因为特效和模型影响到玩家判断。我们会通过在球体后面加一个底或者是圈之类,用来准确表现球体大小。

2.如何在把控好包体大小的前提下,去提升游戏的画质和内容?

王国祎:在游戏资源里,占用体积最多的就是贴图,球球运营到今天也积累了非常多的皮肤资源,在贴图的压缩格式上我们是按目标平台区分处理,比如Android平台会使用ETC和ETC2,iOS平台使用ASTC和PVRTC。

还有就是控制贴图尺寸,因为最终游戏的运行平台是手机。制作贴图的尺寸标准应该按照手机的分辨率来限制。另外,资源打包时要把依赖的共用资源拆分出来处理,减少冗余资源。

比如球球的推广包就只包含不到50MB的基础资源,更多的资源是在玩家过了新手阶段后才会引导下载。

3.优化过程中有哪些印象深刻的部分?

徐宇峰:《球球大作战》作为一款炫酷的竞技游戏,最核心是流畅的手感,优化中印象最深的是要保证所有机型有30以上的帧率,并且帧率要平稳不能有波动。为了达到这个要求,我们需要从美术到技术,GPU到CPU,方方面面做好优化。

为此我们把游戏整体优化分解为多个部分,如游戏逻辑、网络、资源加载、io、渲染等,组织优化小组负责每个部分,利用各种工具找到各部分的优化点,能解决的及时解决掉,剩下的点优化小组和Unity技术专家一起来讨论解决方案。团队一起努力把每个部分做好优化,就能达到整体的优化效果。

4.玩家的建议为游戏整体优化提供了哪些帮助?

王国祎:早期和玩家沟通最多的渠道是 《球球大作战》的贴吧,还有玩家的QQ群,玩家通过这些渠道直接向研发反馈问题。这两年球球会在全国各地组织玩家见面会,和玩家一起讨论球球的新功能、新玩法,听取玩家的想法和需求。

在见面会上和玩家也有很多互动交流方式,玩家也很喜欢这种形式,很多玩家都是提前2个小时就到现场。这种方式也让研发人员快速准确地了解到玩家的问题,并且迅速有效地提升体验和解决问题。

5.传统优化方式是否还适用于未来行业的发展?

徐宇峰:传统优化是游戏的优化基础,是游戏前辈们宝贵经验所总结出的经典优化方法,实际上绝大部分优化都是采用传统方法。

但随着游戏品质不断提高,提升游戏性能难度越来越大,当创新玩法结合精美皮肤在传统优化无法完美解决时,我们就需要在传统基础上创新优化方案,让新玩法与高品质美术组合能流畅的运行。

6.如何看待游戏对美术品质需求日益增高的趋势?

徐宇峰:目前游戏的美术品质在不断提高,虽然新手机性能也在不断提升,但远远赶不上游戏品质的提升速度。游戏画质的提升,除了带来更好的视觉体验和操作感以外,更重要的是,游戏画面、场景、人物细节的丰富完善,能让玩家对游戏的品质提升认可度,很多玩家对游戏第一印象就是画面是否精致。

而在美术品质不断提升的同时,渲染压力也越来越大了。因此,为了保证游戏的流畅性,渲染优化变得越来越重要,而Unity引擎也在不断优化渲染管线,让渲染性能越来越高。

Ben

Ben

线上线下专访、稿件发布合作请联系QQ或微信:328624956

评论已关闭!

相关资讯