在5月13日Unite 2017 Shanghai 的案例分享专场上,巨人网络的李东旭分享了《球球大作战》《(下文简称《球球》)客户端优化经验。 李东旭主要从两大方面做了分享,一是《球球》的版本迭代问题,二是基于《球球》独特的游戏特性分享了同步、卡顿和地图实时显示三方面的解决方案,详细内容如下:
我是李东旭,来自巨人网络,目前在《球球》项目组从事游戏性开发、功能开发还有系统优化工作。今天给大家带来的是《球球大作战》客户端优化经验分享。主要分两块,第一块讲的是关于版本的,第二块是关于遇到的一些问题,以及解决方案。
先来简单介绍一下这个游戏,《球球大作战》是全球首款实时对战的休闲手游,一经推出就受到Iphone、安卓双端推荐,迅速风靡全球,取得众多佳绩,深受玩家喜爱。目前该游戏已在全球100多个国家同步上线,并在苹果App Store中国区游戏免费榜稳居Top10,日均百万玩家的在线,上亿玩家已投入并热爱了这款游戏。
怎么样做到三周一个更新版本?
《球球》是2015年5月份立项,第一个版本两周后就上线了。这个版本主要是核心玩法,两个人,一个前端一个服务器。因为这个玩法比较新颖,无法预估玩家的情况,所以第一个版本就尽快让它面对玩家,让玩家来评估这个新颖的玩法的接受程度。没想到一推出,玩家发现这个游戏非常好玩,非常新颖,以前在手游上没见过。之后我们就大力地去推进这个项目,你可以看到,下面这些版本,基本都是每隔两周,最后三周就发布一个新版本。我讲这个地方的目的是什么?目的就是告诉大家,我们这个版本推进速度是非常快的。
其实直到现在,就是昨天我们也发了一个新版本,基本这两年,每隔两到三周就发一个新版本。这里跟普通的大型手游有区别,区别就是一般的大型手游,他们的开发时间就耗时比较长,从立项到第一个版本见玩家,基本就已经大半年以上了。
这种情况下,如果是有过大型游戏的经验还好,但是对那些没经验的团队来说,这个危险性是非常高的。你不知道你做的这些东西,玩家喜不喜欢,很有可能就失败了,失败程度概率是非常高的。
这里就给大家展示一下,我们的版本的一个迭代体系。我们先有一个需求,有一个需求之后,我们就进行开发,开发完成之后就立马进行测试,OK的话就直接发布了。这个周期就两到三周,两到三周做完之后,发布之后,然后下一个版本也是这样一个循环。这样有一个好处,迭代非常快,在做完一个核心玩法之后,马上发布出去来验证这个玩法到底好不好。这个在游戏前期,效果非常好,但是到后期,你的项目越来越庞大,已经很难做到两到三周了。尤其是测试这一块,测试的工作量越来越大,所以这块我们引入了一个测试服的体系。
我们单独做一个版本,这个版本比我们的现在版本功能要新许多,一些新的东西在里面。这个版本给部分玩家用来测试,测试的话,就需要激活码,这样保证一部分玩家能优先玩到新的功能,然后根据新的功能,我们就根据玩家反馈来继续完善,OK的话就发布。这个地方就跟MI ui的开发版跟稳定版挺像的,有了测试服之后,也不是完全的完美,在后面项目越来越复杂,两到三周也很难达到,我们还是尽量在两到三周之内做完一个版本。
为了更加完善我们的玩法,还有需求,我们加入了一个玩家反馈的体系,有了这个体系,我们在功能方面,能更正确地做一些选择。这里的玩家反馈大概有这么多,主要的就是通过QQ群,还有游戏反馈,还有玩家见面会这三个大块来直接面对面跟玩家沟通,取得玩家的建议,尤其是每次版本发完之后,有可能会遇到一些问题或者bug,通过游戏内的反馈,能及时看到一些问题,然后通过更新,可以立刻解决。
第一部分已经讲到这里,接下来我分享一下,在之前那些版本迭代过程中,遇到的一些问题,以及我们怎么解决的。主要是三个问题,第一个问题是同步问题,第二个是卡顿的问题,第三个是我们年初的时候做了一个Lbs的玩法,怎么把那个真实的地图显示在Unity里。
我们先看同步问题。我们是一个实时对战的手游,在同步这块肯定免不了,我们也在一些同步的机制上、模式上,也做了一些选择,然后根据我们游戏的特性,选择合理的同步方案。
同步问题:
《球球》的游戏特性体现在哪?同步方案要怎么选择?
一,《球球》这个游戏主要是球跟球之间的关系,它们的关系规则简单,可以用公式来概括。用的最多就是一些物理的公式,这些比较简单,我们就很容易做出来。
二,快速游戏,这个游戏中途可以随意加入退出,而且我们的进入游戏是没有载入时间,直接点击按纽,就直接进去了。
三,实时观战,玩家可以观战其他玩家,在这种情况下,客户端是没有任何操作的,全靠服务器把数据发过来。但是这种特性,我们也做了一些选择,最终的方案是状态同步的一个机制模式。这个模式有一些好处,就是开发效率比较高,这个开发效率是相对而言,可能对别的游戏状态同步可能比较麻烦,但是对我们游戏这种机制,其实开发效率非常高的。然后客户端的计算量大大降低,方便性能优化,就是客户端的一些球跟球之间的逻辑,因为用公式来概括的,而且球跟球之间的计算,因为球很多,所以计算量非常大,这块客户端是不需要计算的,直接通过服务器计算,然后把结果发过来。因为是在服务器上算,这块反外挂过来也比较简单。
四,断线重连,因为计算都在服务器,所有信息都在服务器,一旦断线,就可以立马连上去,恢复当前的状态。传输协议,我们现在用的是TCP,TCP这块,其实我们现在用的是,大部分情况下还好,主要在延迟情况下,TCP比UDP要更差一点,之后的话会逐步替代成UDP,或者是TCP和UDP共存的情况。
我们看一下
服务器逻辑
。其实第一个版本我们服务器是不参与计算的,就是P2P的模式,客户端跟其他客户端相互连接,服务器只负责转发客户端之间的消息。这种情况下发现延迟非常高,因为手机跟手机之间,还有网络跟网络之间都是不一样的,大多数情况下你看到一个球,另一个玩家就没看到,然后他被吃了,他不知道怎么回事。所以第二个版本就把计算全部挪到服务器上。服务器这块也是模拟一个流程,就是50帧每秒的刷新,模拟一个真实的环境,发给客户端的话,就是10次每秒,主要发一些球的坐标跟速度,还有吃跟被吃,还有删球加球的逻辑。为了优化这个流量,因为这种同步方式对流量要求比较大一点,所以我们对客户端发送的话,只发送客户端视野里的数据。
看一下
客户端的逻辑
。客户端的话同步方式就用了一个影子追踪的方式,然后只发送操作数据,这块服务器十秒一次地发过来,我要经过转化,然后把它变成一个数据球,然后数据球的话,是不参与渲染的,这个数据球在Updete里面一直在跑,如果网络延迟,这个球还在跑,保证这个数球跟服务器对应的球是同步在运动,不会因为网络的停止而停止移动。渲染球主要跟着这个数据球作为一个插入平滑,一直追着它跑。这样有一个好处就是,当网络波动的时候,数据球可能会抖动,但是渲染球一直在平滑,在玩家看来基本感觉不到。这个其实就是在网络延迟非常大的情况下,还是因为卡顿,就是延迟,玩家可能操作不太流畅,这块我们还在做深入的优化工作。
卡顿问题:
《球球》游戏内的特殊卡顿问题优化策略
第二个问题就是卡顿问题,卡顿问题基本大家都遇到过,然后就是怎么优化的话,网上做优化的有很多的方案,这块就相同的优化点,我就不怎么详细说了。主要介绍一下我们这个《球球》在卡顿这块的一些,因为
特殊原因造成的卡顿是怎么优化的。
卡顿一:光环、圣衣组建卡顿的处理
卡顿的话,大概就这么些,《球球》主要卡顿点就在于,因为服务器是十次每秒刷新,因为是十次,不像客户端帧数比较高,所以你发一次的话,这个数据量里面球的数量其实非常大的,就引起了一个问题。问题是发过来这一刻,要处理大量的数据,会造成卡顿。还有就是美术方面的问题,因为我们球上面挂了很多组件,这些组件尤其光环和圣衣这个东西越做越炫,会引起卡顿,而且我们一局游戏,有50多个人,而且中途还会再加入新的玩家,如果提前进这局游戏之前把所有东西都加载到,这个内存是肯定承受不了的。而且我们加载是没有立即进入游戏,这就造成一个问题,我们必须要在玩的过程中来加载美术资源,这样也会引起卡顿。
遇到一个卡顿的话,我们得找这个卡顿在哪里?然后找到的话,我们得分析是由于什么东西造成的。《球球》这块,刚才也整个介绍了一下,主要就是这两个地方。先看一下球体组件的加载,球体组件的话,我们光环跟圣衣现在已经有几百多个了,有三百多个,最坏的情况下,可能每个玩家用的光环跟圣衣都不一样,这样在一局游戏里面都显示出来的话,对游戏的内存,及其渲染,其实压力非常之大。这个只是一部分,主要是光环。现在玩家审美要求越来越高,我们做的东西也越来越炫,这样造成非常多的卡顿,接下来给大家介绍一下我们是怎么优化这块。美术这块优化,这次没怎么讲,因为网上美术这块怎么优化有很多,我主要讲是怎么加载的。
我们先看一下组件的构成,一个球本体是一个球,这个球其实是一个2D的一个慢视平面的,然后名字,名字这块我们是用自己做的一个,等于是自己写,自己写的好处就是效力比较高,可以走Unity自己的那个合P(音)流程,然后那个国旗也是一个慢视,不是用UI做的。还有光环、拖尾圣衣,还有箭头,这些加载压力都非常大的。我们是怎么优化这块,优化主要用到分帧处理。
分帧处理大家应该多少都了解到就是把一堆大量的计算全部拆开来,分散到到各个帧里面,这样的话帧数就很平稳,不会出现一个大的CPU曲线的波峰。每个球依次进行加载,一个球加载完了,再加载另一个球,这样的好处,有可能球2还没有加载完,就已经被吃掉了,这样有一个好处,我们就减少了大量的计算,大量的加载。而且玩家看的话也是比较流畅,不会出现突然画面不动,然后又开始动了的那种情况。
卡顿二:大视野大量球的刷新卡顿
然后优化后,我们发现帧数是上来了,但是还是有很大的波动,这块主要原因就是
大视野大量球的刷新卡顿
。因为我们的游戏视野是不固定的,不像其他游戏视野一直固定的,在同一屏里面看的东西基本不会高的太多,我们游戏就不同了。有可能一个屏幕里面,可能看到成百上千个元素还有物体。而且玩家在玩的过程中,如果玩得好的话,视野是来回变动的,服务器发数据的话,因为只发我们看到的数据,所以我们玩家在来回切换的情况下,服务器发的数据也是很多的,就是大量的球跟添加删除,这样的一个操作对客户端的压力也非常大,所以客户端的话,就需要做一些计算,一些处理,这里就很考验一个场景管理的框架。