手游实时对战初步解决方案

原创 2016年09月24日 17:48:01

某个周一上班,项目经理在项目组里定了个目标:实时对战开搞,两周后能在手机上撸一把。

负责客户端的同学和我表示震惊。WTF,两周内做完,没啥思路,咋搞~!@#$%^&*()

先对实时对战的难度作一个大概的描述吧。时下挺流行的一款手游——拳皇98online,其实时对战属于回合制,设计起来较为简单。即便如此,人家开发也是用了几个月时间,刚上线的时候还出了很多bug,回炉重造也花了快两个月。而我们的项目属于RTS(及时策略模式)游戏,各种指定都是同时释放的,设计起来难度也大了很多。

以前在银汉的时候,虽然也接触过实时对战。然而我对pvp同步只停留在“看过猪跑”的概念,要自己动手,发现也是无从下手。

作为一名光荣的程序猿,我觉得不能因自己没做过,就轻易say no,丢给其他同事。不接受一些有挑战性的工作,我们什么时间才能强大起来呢!?

接了需求,查了好久资料,也请教了一些有经验的同学。两天后,开始coding...

网上关于实时对战的功能不算少,但过于理论化,碎片化。而且同样一篇文章,却有很多不同的url(程序员喜欢一字不漏复制粘贴代码,文章也不放过)。在这里,我希望对我的实现作一个总结,争取尽量将设计思路步骤化,剩下的实现细节就不展开了。

Given much time, it works perfectly;Given little time, it can only work.

在两周时间内,我们设计的pvp只需要能够打得起来就可以了。基本跑起来的定义是什么,至少两个人打同一场比赛,看起来画面差不多一样,而且不能出现在各自的屏幕里对方都输了,那就尴尬了。

实时对战是一个大工程,如果不考虑弱网性和客户端作弊,那服务端设计就非常简单了,因为它只需要针对以下几个方面作消息转发就好了。

一、位置同步

游戏中两人的行走,是同步的基础。由于策划强烈要求顺畅性,我们只好采用弱同步了,只要玩家在本地产生了移动指令就能行走。方法是这样的,客户端A以一定的频率(例如200ms一次)将移动指定发送到服务端,然后服务端再转发给对方客户端B。其实这里就出现了延时,延时在A发包到服务端所用时间以及服务端下发到客户端B所用时间之和。在本地局域网延时可忽略不计,后面会有改进。

二、技能同步

同样因为要求顺畅性,所以只要客户端验证通过(CD和攻击范围等等),就应该同步技能了。这里又出现了跟位置同步同样的延迟了。这里有个策划方面的技巧,如果策划设定技能的释放能有一个起手动作时间,那么这一小段动作时间就可以隐藏网络延时带来的时间差。释放一个技能,首先播放一个技能起手动画,然后马上发出指令。理想情况,当动画播完了,双方刚好收到技能释放包,于是一个技能完美地在双方客户端释放了。在这里吐个槽,实时对战由于网络延迟存在的客观性,策划应该想方设法通过一些规则隐藏一些弊端,而不是坚持己见,一旦程序实现不了就说他们的开发太水。=。=

三、血量同步(死亡同步

血量同步包括技能产生的伤害以及英雄单位本身回血都需要同步。毫无疑问,双方英雄单位的血量都是保存在服务端。当一方的英雄全部死亡的时候,就可以判定胜负结果了。血量同步是整个设计中唯一需要加锁同步的,不然就有可能出现双方最后一刀刚好把对方打死了,这时如果不加锁,就有两个赢家了。

这里抛个问题,技能伤害包应该由攻击方还是防守方发送?

答案当然是以攻击方的屏幕为准了,试想一下,假设因为网络问题或者防守方故意把游戏退到后台,以防守方为准的话,技能包不就丢失了!

四、buff同步

对于一个魔法类游戏来说,一场战斗会触发各种各样的buff效果,例如属性buff,状态buff,伤害buff。关键的是,由于大部分buff都会影响属性,进而影响伤害,所以不得不放在服务端运行。因此buff同步是全部同步类型中最难的部分,基本是把客户端的代码用服务端语言翻译一遍。由于buff复杂,因此不在两周的工作内容之内。

通过简单的消息转发,把以上几种类型的同步实现了,就可以放心地交货了。

两周后,经理在自己的手机上跟另一同事撸了一局,这时,无关比赛结果。看到经理露出了一丝微笑,我知道我可以安心下班鸟。(^-^)

都说pvp同步是一个大工程,两周做出的东西只能说一个骨架,接下来还需要考虑深层方面的诸多问题。

关于强同步与弱同步

战斗同步从指令释放是否需要服务端的同意为准则,可分成强同步和弱同步。强同步是指客户端发出的指令必须由服务端验证通过才可以释放。比如,客户端发出的放技能指令,需要服务端验证能不能放,有没有被控制等等,验证通过才告诉客户端可以释放了。而弱同步就是,不管服务端有没有同意,反正我本地判定可以放技能就放技能,可以走动就走动。

强同步设计起来比较简单,但在网络延迟的情况下,玩家会埋怨技能老是放不出来,或者老是在原地跑步。选择哪种方式,需要跟策划说明商量。

关于位置网络延迟

手游的网络环境不像端游那么稳定,特别是在Wifi的环境下进行游戏。比如你在玩游戏的时候,突然面前来了一个胖子,或者上厕所关了一下门,网络就会突然断了。因此,客户端发出的一个指定,可能服务端收到的时候已经过去一段时间了,再转发到另外的客户端又需要另外一段时间。同步位置的指令参数应该包括目标位置,移动的方向,以及到达目标的时刻,这样在玩家A的位置同步给玩家B的时候,我们可以根据数据包到达B的时刻t1与理论到达目标需要的时刻t2。若t1<t2,说明数据包没有延迟,那么就让玩家A的镜像重新计算速度,保证两边客户端玩家A的位置同时到达目标;若t1>=t2,说明数据包已经延迟了,比较简单的方式可以直接让玩家A的镜像直接拉扯到目标点。

关于客户端对时

如何保证对战的双方的逻辑时间一样呢?我们只要保证双方都以服务器的逻辑时间为准就好了。这里不是要求将两边客户端的系统时间调成跟服务端一样,只是逻辑上一致即可。方法可以是这样的,在比赛开始的时间,客户端发送一个对时请求到服务端,记下此时客户端的时间t1,服务端收到指令后返回当前的服务端时间ts,客户端在t2时刻收到服务端的响应包。我们假定数据包上行下行所需时间是一致的,那么在客户端收到包的时候,服务端时刻为 ts' = ts + 1/2*(t2-t1)。那么客户端与服务端的时间差delay=ts'-t2。以后客户端发包的时候就可以加个时间戳delay+t(now),代表客户端相对于服务端的逻辑时间,服务端与对方客户端 可以直接根据这个时间戳判断数据包是否延迟了。这里有个问题,如果服务端收到的时间戳比服务端当前的时间还大,那么就说明当初对时的时间网络不好,这时,重新发个指令让客户端再对一下时就好了。

关于伤害验证

对于客户端传上来的伤害,服务端不能百分之百信任,所以服务端也需要按照客户端的逻辑把伤害计算一遍,如果两者误差在容许范围则通过,否则以服务端计算结果为准。这就要求服务端需要有玩家属性相关的数据,以及buff状态等等。

关于服务端buff系统

害在服务端计算直接导致服务端需要运行buff系统,因为buff是有时效性,buff会影响属性,会影响玩家状态(例如免疫伤害的buff效果直接将伤害无效化)。由于每个单位都可能挂有buff,而服务端需要同时支持数以千计的玩家在对战,因此验证buff的定时器不宜跑得太频繁。

关于游戏初期无人匹配对手的问题

游戏上线初期没什么人气,或者冷门时间端上去玩,都有可能出现玩家匹配不到结果。这时,比较简单的处理方式是当玩家匹配不到真人的时间,直接服务端返回一些机器人数据就好了,那么这时就是伪pvp了。或者找一些比较有空的策划啊,测试啊,在上班时间上线陪练也可以。游戏也有点像魔法,有时需要甩一些障眼法,哈哈

版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

腾讯如何打造一款实时对战手游

2015年以来,手机游戏的市场偏好,逐渐从早期的休闲类、跑酷类、卡牌类游戏,转向重度、操作性更强的ARPG 、FPS、、MOBA类游戏。因此实时对战这一游戏玩法,也逐渐成为了手机游戏的一个核心玩法。纵...

Spring定时器的两种实现方式

有两种流行Spring定时器配置:Java的Timer类和OpenSymphony的Quartz。 1.Java Timer定时 首先继承java.util.TimerTask类实现run...

【游戏编程】AI-迷宫寻路算法-深度优先搜索和广度优先搜索

状态空间搜索,如果按专业点的说法就是将问题求解过程表现为从初始状态到目标状态寻找这个路径的过程。通俗点说,就是在解一个问题时,找到一条解题的过程可以从求解的开始到问题的结果(好象并不通俗哦)。由于求解...

腾讯如何打造一款实时对战手游

2015年以来,手机游戏的市场偏好,逐渐从早期的休闲类、跑酷类、卡牌类游戏,转向重度、操作性更强的ARPG 、FPS、、MOBA类游戏。因此实时对战这一游戏玩法,也逐渐成为了手机游戏的一个核心玩法。纵...

webservice接口实现数据共享的实现的初步解决方案(更新、删除)

数据同步是掌上电脑能够迅速实现与台式机、笔记本电脑或者不同数据库中的数据同步与信息共享,使自己的数据保持完整性和统一性。 数据库的双向主从双写并双向同步场景,主要考虑的是数据完整性、一致性和避免冲突;...

【Expression 序列化】WCF的简单使用及其Expression Lambada的序列化问题初步解决方案(二)

接上文 【Expression 序列化】WCF的简单使用及其Expression Lambada的序列化问题初步解决方案(一)  上文留下了一个问题没有处理,但最后也找到了相应的解决方案,下面就来说...

【Expression 序列化】WCF的简单使用及其Expression Lambada的序列化问题初步解决方案(三)

接上文【Expression 序列化】WCF的简单使用及其Expression Lambada的序列化问题初步解决方案(二)   上文最后留下了一个问题,引起这个问题的操作是把原来通过硬编码字符串来...

【Expression 序列化】WCF的简单使用及其Expression Lambada的序列化问题初步解决方案(四)——关于Guid的问题

发了本系列的前三遍几天后,收到了若风云 同学的站内信,说如果Expression中包含Guid类型属性的查询时,会报异常,亲自验证了下,确实会有问题。原因是Dynamic Expression A...

手游充值问题全套解决方案

  • 2014年08月27日 13:49
  • 280KB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:手游实时对战初步解决方案
举报原因:
原因补充:

(最多只允许输入30个字)