干货 聊聊吃鸡游戏使用的关键技术
姜雪伟,3D引擎专家,主要擅长3D图形学渲染,客户端架构,服务器架构设计,虚拟现实,C++编程等技术,曾就职于网龙,久游,趣游等多家IT公司,参与研发多款游戏上线;已出版著作《手把手教你架构3D游戏引擎》电子工业出版社,《Unity3D实战核心技术详解》电子工业出版社,《Cocos2D-X 3.X 3D图形学渲染技术》电子工业出版社等IT书籍。 【内容简介】市面上最火的游戏,当属《绝地求生》,该款游戏从端游到手游吸引了大量的玩家,网上有人从策划角度,分析过关于该游戏的一些核心玩法,以及如何做到吸引玩家的,但是还没有从技术角度对该款游戏进行过分析,本篇文章就从角色动作、游戏渲染、角色网络同步、大地形加载、四点关键技术角度对其关键技术给读者进行解读。 目前,市面上最火的游戏,当属吃鸡游戏也就是《绝地求生》,该款游戏从端游到手游吸引了大量的玩家,网上有人从策划角度,分析过关于该游戏的一些核心玩法,以及如何做到吸引玩家的,但是还没有从技术角度对该款游戏进行过分析,本篇文章就从技术角度对其关键技术给读者进行解读,吃鸡游戏采用的是UE4虚幻引擎制完成,作为程序爱好者,我们应该本着学习的态度去玩,深入理解游戏产品背后的技术支撑,这样我们从玩中也能学到知识,否则就会走向另一个极端沉迷其中,把自己玩废了。 今天,我们主要从这四方面给读者介绍相关技术实现:角色动作,游戏渲染,角色网络同步,大地形加载。它涵盖了吃鸡游戏的关键技术,掌握了这四点就掌握了这款游戏的核心技术,UE4引擎市面上使用的比较少,而且它对程序员编程要求也比较高,我们就以最常用的Unity引擎为例给读者介绍吃鸡游戏使用的相关技术,成熟的商业引擎,它们的技术大同小异,UE4能做的事情,Unity引擎基本也可以做到,吃鸡游戏的角色动作特别多,我们就先从角色动作讲起。 角色动作 玩3D游戏时,经常会看到游戏中的3D角色非常绚丽的动作表现,游戏中的角色动作主要是通过美术制作完成,制作方式有两种:一种是通过动作捕捉,然后再由美术人员根据捕捉到的数据完成美术制作;另一种是美术利用Max或者 Maya工具直接制作完成。相比前者动作比较逼真,成本也高。我们这里不讨论使用哪种方式,对于动作类游戏,吃鸡游戏的角色动作是最多的,它包括:跑,走,跳,翻墙,趴下,驾驶载具,扔手雷,装备不同的枪械,使用不同的枪械射击动作,救护,拾取弹药装备等等,为了让读者有个总的认识,通过图示的方式,展示如下所示: 上图,我们列举了吃鸡游戏中角色的大部分动作,这些动作美术都需要完成的,这里就涉及到一个工作量问题了,我们将其分成两类:一类是按照动作要求全部把动作做一遍,工作量是相当大的,因为你不但要制作还要维护这些动作;另一种是采用引擎提供的动作融合技术,这需要我们将动作进行分类,目的是减少一部分动作的制作,这种是最优的方案, UE4引擎也是支持动作融合技术的,下面就给读者详细介绍动作融合技术的使用。 动作融合 其实不论是虚幻引擎、Unity引擎还是自研引擎,成熟的引擎都会提供动作融合技术,为了方便读者学习,在这里我利用Unity的动作融合机制实现了吃鸡游戏中角色的大部分动作,下面先看看我们实现的动作融合状态机。 Unity为我们提供了动作状态机,鉴于吃鸡游戏动作的复杂性,上图是我们模拟实现了一下,我们在这里将动作进行了分类,分几层无所谓关键是能解决问题就可以,我们这么分的原因是方便对角色动作进行融合,层与层之间的播放可以设置优先级播放,也可以同时播放,这样我们就可以实现动作的融合了。 先给读者介绍一下我们为什么这么分层?如果使用一层来实现角色动作状态机,这么多动作显得非常臃肿而且动作之间的转换非常复杂,灵活性不够,让开发者很容易深陷其中,逻辑很难理顺,所以我们采用了分层的策略,这样动作的播放顺序,动作的融合在逻辑方面会很清晰的,首先看Base Layer,它是最核心的层,该层主要实现的是角色基本动作的播放,我们通过思维导图的方式给读者展示: 我们将Base Layer层设为父类,再看OnlyArms层,它继承于Base Layer,如下图所示: OnlyArms层主要是在Base Layer层的基础上做了一个扩展,比如加了一个角色拿不同的武器待机状态,继承原理跟C++,C#等面向对象语言的继承方式类似,OnlyArms层的部分有限状态机如下图所示: 另外,UpperBody层主要是针对角色上半身的动作状态机,便于与Base Layer或者OnlyArms层做动作融合,UnderBody跟UpperBody类似,它是下半身的动作状态机。 下面我们以角色装备武器时的走,跑为例给读者讲解动作融合,先展示角色装备武器的基本动作:待机,走,跑动作混合树示意图: 动作之间的过渡,我们运用了2D 笛卡尔插值计算,2D笛卡尔插值是系统为我们提供的,走的动作就有四种走动方式,它朝四个方向行走,如下所示: 我们已将其实现出来了,它在我们的Demo中的效果如下所示: 吃鸡游戏中的画面如下所示: 给读者讲解如何使用动作融合解决问题,以角色拿枪移动中进行射击为例,我们可以将这个动作分解成两部分:一是角色拿枪走动,二是角色站立射击,这样我们可以通过程序把二者做个融合,融合的结果是:角色的下半身采用角色拿枪走动,而上半身采用站立的射击动作,这样我们就把两个动作融合在一起了,在具体实现上,我们有UpperBody层,该层会与我们的OnlyArms(该层继承Base Layer)做动作融合,先展示上半身的射击动作状态机: 射击动作包括:步枪射击,手枪射击,RPG射击,将它与OnlyArms层的站立射击进行动作融合就实现了角色边走动边射击,后面我们会提供案例实现代码,实现效果如下所示: 这样角色的边走动边射击的动作完美融合在一起了,关于动作融合在这里也要注意,不能所有的动作都考虑到融合,融合也要本着一个原则,动作融合时要保持动作的协调性,比如不能把不带武器的走跟射击动作去融合,那样就会出现动作的不协调性,因为角色空手走动与拿武器走动是完全不一样的动作表现,吃鸡游戏在动作融合这块做的比较多,我们采用动作融合可以帮我们减少美术的工作量而且角色动作要制作成独立的动作文件,这样有利于动作的调优,我们是通过技术推理实现了吃鸡游戏中的动作播放。 在吃鸡游戏中,角色可以使用不同的武器,而使用不同武器的动作也是不同的,相应的武器的子弹效果也是不同的,武器效果可以通过特效和数值表现,不同武器的子弹发射轨迹可以通过插值算法完成,在此我们也模拟实现了不同武器的发射效果,图一是肩扛式的火箭筒发射效果图: 图二是手枪射击效果图: 图三是散弹枪射击效果图: 另外还有冲锋枪等,吃鸡角色的其他动作实现跟我们上面讲的类似,这里就不一一介绍了。 装备的切换 我们可以看到在吃鸡游戏中,角色在地面上能捡到很多装备,包括枪支,弹药,背包,头盔等等,这些物品除了放在游戏中的背包外,我们也会选择一些装备挂接到角色身上,装备切换怎么实现的呢?其实它跟我们的换装类似,需要在角色的骨骼上挂载不同的虚拟点,具体实现如下图所示: 图中画红线部分就是我们说的虚拟点,它们都是作为骨骼动画下面的子节点,一定要注意是在骨骼下面,因为这些虚拟点是跟随角色一起动的,换句话说,它是角色身体的一部分,在吃鸡游戏中的角色装备画面如下所示: 当然,我们也验证了我们的切换武器方式,实现的效果如下所示: 当然角色本身还需要做一些优化处理,我们对角色使用了LOD网格,根据摄像机距离远近使用不同的LOD角色,角色动作我们就介绍到这里,下面我们讲讲游戏渲染技术。 游戏渲染 不论是什么类型的游戏,游戏的渲染效果直接决定了游戏的品质,吃鸡游戏也不例外,游戏渲染包括两方面:一方面是物体的材质渲染,另一方面是场景的后处理渲染。物体的渲染主要是针对材质贴图的渲染,比如高光,法线,反射,折射,环境映射等等,另一方面是场景的后处理渲染也称为滤镜渲染。UE4渲染非常强大,对于材质要求也比较高,相比Unity更容易掌握,下面我们还是以Unity为例给读者分析,先分析吃鸡游戏的角色渲染,如下图所示: 上图显示的角色钢盔,枪支都有明显的高光效果,它的枪支和头盔都是用了高光法线效果,Unity也为我们提供了该技术,我们用Unity模拟实现了一下效果,如下图所示: 效果也很炫的,以上是针对角色的材质渲染,Unity给开发者提供了材质渲染的Shader,如下图所示: 另外,场景中的一些物件渲染,比如草地,树木的生成,这些都可以使用GPU编程实现,程序员如何编写Shader?引擎也为我们提供了Shader编辑器,比如Unity2018使用了Shader Graph,还有一个Shader Forge插件,UE4的蓝图,这些编辑器不需要开发者编写程序代码,直接通过拖拖窗口界面就可以实现。吃鸡游戏也使用了后处理渲染,比如实时阴影,还有游戏中的Bloom,Blur效果等。其实这些都是成熟引擎的标配,关于渲染,UE4使用了多线程渲染,Unity从2018开始也有了自己的多线程编程渲染,下面再给读者介绍吃鸡游戏角色同步机制。 角色同步 吃鸡游戏采用的是开房间性质的,使用的网络同步是帧同步,游戏中的同步方式分为两类:帧同步,状态同步;状态同步在ARPG游戏中使用广泛,因为角色的动作需要跟服务器做一个验证,这样客户端之间会有一定的延迟,但是数据一定是准确的。而帧同步则不需要这么操作,它要求的是动作的一致性,如果某个客户端慢了,后面为了赶上角色动作,会加速播放,以满足所有客户端同步,其实以前的游戏比如CS游戏使用的也是帧同步,还有篮球游戏等等。其实帧同步和状态同步没有好坏之分,根据游戏产品的需求不同,采用不同的同步方式。 每种同步都有自己的优缺点,因为吃鸡游戏使用的是帧同步,本篇文章重点介绍帧同步。 我们先分析帧同步的注意事项: 数据传输会有浮点数的问题,不同的平台处理浮点数的方式也是不一样的,我们需要将浮点数改为整数进行传输采,用的方式是把浮点数乘以1000或100然后取整,针对特定的数据对象来编写序列化函数。以下模拟实现代码如下所示: 另一个注意事项是加速播放,由于各种原因客户端收到“过去时间”里的一堆网络帧,因此,客户端必须要有处理这些堆积起来的网络数据的能力。最简单的做法就是加速播放(快进)。 实现效果如下图所示: 对应的实现代码实现如下: 最后一个要注意的问题是断线重连/中途加入,需要做到在服务端保存每一份同步包,这样服务端只需要记录每个玩家的初始数据,在新玩家加入游戏时,首先发送每个玩家的初始数据给新玩家同步,然后再把所有同步包打包发送给新玩家,让新玩家一次性Update,即可完成中途加入。当然不要忘记给现有玩家发送新玩家的数据。模拟的代码如下所示: 帧游戏收发频率,通常服务端每秒20-50次向所有客户端发送同步包。我们采用的是乐观锁,就是服务端每隔一段时间发送同步包,然后客户端每隔一段时间接收并应用之,如果在那段时间内没有收到,就持续等待。每Update一次即是一帧,每次Update的间隔时间为17毫秒,这个数字是根据(1/60)秒取整得出。每隔三帧服务端便会发送同步包,而客户端则是每帧都会接收,每隔三帧便会应用之,通常称为同步帧。 帧同步游戏技术,并不存在一种可以让游戏流畅的通用做法,而是需要和游戏具体做很多结合,在减少数据包,优化游戏快进体验,控制发包速度上尽量调优。同时还需要和游戏产品策划一起,平衡一致性、实时性、公平性的策略,才能真正达到流畅游戏的目的。 地形加载 吃鸡游戏中使用了大地形的加载方式,大地形的加载方式,首先是分块,然后采用预加载方式进行,为了效率优化可以使用多线程的方式,UE4引擎本身就支持多线程,更容易实现大地形加载,下面就给读者介绍如何使用多线程实现大规模地形的加载,吃鸡游戏的场景如下所示: 从吃鸡游戏中的地形我们可以看到,它里面的建筑物是非常少的,其实它这么做的原因是把内存留给了网络数据通信,毕竟每个玩家都是通过帧同步的,每个玩家会同时发送和接受大量数据的,这需要占用很多内存的,这也是做了一些优化操作的。如果树木和建筑物多,那就需要做一些裁剪操作比如OC裁剪,但是这样会影响游戏体验,所以吃鸡游戏就做了一个折中方案,减少建筑物的渲染,做好帧同步。 我们回到大地形加载方案实施上: 首先对数据进行分块存储,将人的视点所能观察到的范围的数据作为一块,将整个地形分成若干个这样的块,以块为单位进行存储。 我们采用的是双缓存技术,当视点在A区域时,加载九块到显存中,开辟一个数据读取线程,从磁盘中的J-Y数据块加载到内存中。当视点从A区域移动到l区域时,将显存中的对应数据块与内存中的数据块替换,同时从磁盘中加载新的数据块,放到内存中。 给读者进行案例展示如下所示: 另外,大场景地形中使用了非常多的贴图,下面介绍如何优化?所有程序用到的贴图会被pack到几张非常大的虚拟贴图上,模型的uv也被转为虚拟贴图上的uv,这些虚拟贴图尺寸通常非常大,无法全部载入内存,每个虚拟贴图会被划分为很多n*n的小块,每个小块称为一个page文件存在磁盘上, 虚拟贴图会对应一张indirection texture,这张图是载入内存的,indirection texture上存储了每个虚拟贴图的每个page块位置所对应到的真实贴图(或物理贴图)的位置。 当前画面需要访问某个虚拟贴图上的某个page的时候,通过indirection texture找到它在物理贴图上的位置,如果物理贴图上不存在,就查找到它对应的磁盘上的page文件,将其载入物理贴图的对应区域。shader在渲染的时候,结合indirection texture去访问物理贴图来采样。 对于虚拟贴图也要处理mipmap,对于虚拟贴图也同时存在它的多个mipmap的虚拟贴图和indirection texture。load 物理贴图的时候同时要load 这些mipmap。 虚拟贴图的具体实现方案如下所示: 虚拟贴图减少了内存占用,但是对于io是一个挑战,尤其在快速转动视角,飞行等快速切换渲染物体的情况下,很多时候加载贴图的时间会成为瓶颈,这是在实现中一个很大的问题。一些优化方法包括每次对page优先加载mipmap最低一层的,最后加载高层的,这样当所需的mip没有加载好的时候,可以向使用最低的那个mipmap,然后待加载好之后再展示细节更高的。 总结 现在游戏开发中使用的技术都是开放的,条条大道通罗马,本篇文章从技术实现以及优化角度对吃鸡游戏的技术做了一个解析,希望对大家开发类似吃鸡游戏提供一个技术参考。 案例代码下载地址: https://pan.baidu.com/s/1G1GZkfjCFQKYbSJqvsxi4w 密码:o3z8 有投稿意向请联系编辑: meixu.feng@msup.com.cn 活动预告: 12月30日—1月3日,TOP100Summit峰会将于北京国家会议中心举办。壹佰案例是科技界一年一度的案例研究峰会,旨在发现有案例教学意义的项目或方法论,每年甄选有学习价值的100件技术创新/研发管理实践,分享他们在本年度最值得总结、盘点的实践启示,累计超过9000位技术团队带头人参与。以往六届参会人员来自近千家企业,覆盖软件、互联网、电商、通讯、金融、医疗、交通、Startup等行业,岗位涵盖产品经理、测试经理、项目经理、架构师、工程师、技术总监、Team Leader、用户体验经理等。 本届峰会,联席主席如下: