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

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

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

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

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

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

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

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

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

目前游戏的战斗同步,主要有两种。一种是状态同步,主要运用于MMORPG类型的游戏。另外一种是帧同步,只要用于RTS,FPS游戏。

在两周时间内,我们设计的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的镜像直接拉扯到目标点。

关于客户端对时

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

关于伤害验证

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

关于服务端buff系统

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

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

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

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

jforgame

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值