选择引擎看实际需求,同步交互为未来发展趋势
整理/手游那点事子安
昨日(6月27日),由网易游戏举办的网易游戏学院第二届公开日《技术进步引发的灵感革命》在广州网易大厦顺利举行。会上,网易天下事业部技术经理、《乱斗西游》项目主程陈伊力就游戏立项时选择游戏引擎的思路及方法、同步交互手游中同步机制的选择等问题发表了演讲。
他表示:在选择游戏引擎的时候一定要从实际需求出发,需要考虑研发时间、画面(2D、3D)、游戏内容、脚本系统以及费用等各方面。同时他认为手游未来应该更好的利用手机的性能以及将会出现更多同步交互的游戏。
以下是其演讲整理稿:
游戏引擎的选择:一切从需求出发
相信大家在做一个新游戏的时候,立项时都会非常困惑。你接到一个指令要做一个游戏,但是不知道该怎么做,要选什么做你游戏的引擎,走什么路线都很不清楚。
当时我们得到的指示说做一个3D的MOBA手游,时间是6个月。一开始定引擎不知道怎么定,就想既然只有6个月,肯定首选比较成熟的引擎。我们就想着一切得从需求出发,既然我们接到指令做3D的MOBA手游,它有一些特殊的东西,可能有迷雾渲染、动态碰撞寻路需求,如果没有引擎源码,没办法做改动,是没办法做得很好的。
还有完善的脚本系统,这也是很重要的。我们还需要完善的编辑器,很多开元的引擎,像OGRE,它们跟教课书一样,但是连一个像样的编辑器都没有。有就是完整的GUI解决方案。另外是费用,最后我们把所有的商业引擎都否决了,就决定采用自研引擎,名字叫NeoX(牛叉),它就是支持3D/2D,支持Pylhon脚本,跨平台,支持多种图形API(D3D/GL/GLE/Metal),完善的编辑器。
发挥手机的性能:多线程渲染
项目初期,性能不达标,领导说你的游戏好卡,没法玩,手感很差。首先,我们发现主线程非常忙,逻辑占了30%,渲染占60%,这些都挤在主线程里,当时我们想有没有可能拆分出来,因为我们端游那边也有一些实践,可能是渲染的运算和主线程拆出来呢?
多线程渲染的概念是什么?就是逻辑和渲染分拆分成两个独立线程。优点是更好利用好多核,并发运算。缺点,是BUG的数量和线程数成正比(死锁/饥饿/Crash)。
想到这个方案后,第一件事做可行性评估。首先是能否在移动平台上实现?实现代价多高?实现后是否有收益?
经过之后的共同努力,游戏得到了极大的优化。在iPad mini上提升了10fps。
手游未来的趋势:同步机制深度解析
我们初期规划时只考虑了异步对战。异步对战,就是把对方数据取到你设备上来,你跟AI打,这是策划深思熟虑后决定的,当时我们立项时觉得中国的网络环境很不好,就不像韩国那边,4G已经很普及了。网络延时对我们网络冲击很大,而且我们的游戏对网络也很敏感。我们设计大量的强制位移技能,我打你并不仅仅是我对你造成伤害这么简单,还可以把你拉过来,如果同步做这个事情,所有的移动操作要等服务器相应后才能动。我们技术释放也有严格的制裁,这些设计会导致我们的游戏对延迟非常的敏感。
所以我们立项之初,做了一个异步对战的模式,到研发中期我们需要为以后做准备,就是WIFI对战,局域网内两个人可以互联。运营初期,20个月后,我们发现中国的网络开始好转了,开始尝试做一点实时对战的东西。它是一个比较临时的解决方案,现在要推出真·实时PVP,后面会讲到真·实时PVP的一些技术。
异步对战只同步角色数据,会把验证数据放在服务器,战斗结果放在服务器,这样就完成了一次对战,流量消耗非常少。如果有一些公司对我们游做过竞品分析,我们的流量是遥遥领先的。并且它可以利用碎片时间,不要求对方在线,很符合国情。但是这不是未来,我们只是初期这样设定一个游戏,慢慢我们要往实时对战方向靠,WIFI对战我们也采用经典的模式,主客机模式。这种方式比较容易实现,我们当时半个月的时间就可以搞定,就是WIFI对战,但是跨不出家门,一旦没有局域网,两个人就打不起来了。
我们运营初期发现,很多竞品也做实时对战的东西,我们觉得自己应该有这样的东西,因为时间紧迫,我们做了一个比较临时的方案,还是基于主客机模式。但是为了实现跨网,我们在中间加了一个Route,所有的指令先发到Route那里,发到主机,然后再读过来,主机很流畅,但是客机实际上各种卡。为了解决“卡”的问题,我们在客机加上客机先行的Trick。这种方式虽然可以打起来,但是客机体验不太好,因为受限于主机技能以及网络状况,所以体验不是特别好。后来我们开始真的做这件事情,我们把所有的运算搬到服务器,大概花了接近一个月的时间,并且我们在底层做了一些迭代,加入UDP连接,可以更高的丢包,更好的适应移动网络。
这里值得一提的是同步机制,同步模型很多种,比较经典的一个是帧同步,就是War3/星际等采用,基于指令驱动各个客户端自计算逻辑。服务端只管分发指令,每个客户端根据完整的规则运算整个战场。这种同步方式的优点,逻辑好不好写先不说,因为流量消耗非常小,只需要同步指令,现但比较明显的缺点,如果断线了需要补帧,就是一旦你的战场状态没有了,必须从头开始,从第一个指令运算到连回去的战场状态,虽然现在有一些办法,做到整个战场布局全部呈现,但是非常困难,我们也运营过这件事情。编码者需要非常小心,因为每个客户端自己算自己战场的状态,所以随机数的要求是零随机,编码者必须非常小心,不能使用任何未初始化的变量,如果里面加了新人,可能遇到一个问题,不小心把一个未初始化的变量用,整个游戏就乱了。
第二种方法,我们最终采纳状态同步。就是LOL/ Dota2都是采用这种方式。客户端只有表现,没有逻辑,逻辑全部在服务器端。它的数据传输量一般来讲比前面的方式大,因为它传输的东西不仅仅只有指令,还有各种状态,但是相对来说实现会容易一些,服务端会承载所有的计算,我们最终采用这种方式的原因,首先我们已经把它写成这样了,前面的方式连数据结构的便利顺序都有要求,如果要让它顺序确定,需要再做一点修改,变成一个有序,并且这个修改会让内存占用变大。
我们在客户端做一些Tricks,一个是客户端移动先行,大部分网游都这么做,不管服务器在什么位置,客户端遥感一动,就先走了。但是跟你服务器真实的位置不一致,那边是你有权利做仲裁的东西,所以必须做位置修正。当角色强制位移时,我们做位置修正,当人把你击退了,我们修正到一个正确的位置。修正的时候我们要根据误差调整,网络数据中断我们采用历史数据做差值。
关于网络协议,我们后来采用UDP,就是TCP有一些不好的特性,它不适合我们游戏,比如说它有一个拥塞控制,完全可靠的协议。使用UDP网络,我们可以更高的丢包容忍度,自己可以做丢包的重发,就是拿网络公平性换我们游戏局部的效率。