大纲
现代多人游戏中,多个客户端之间的通讯大多以同步多方状态为主要目标,为了实现这一目标,主要有两个技术方向:
状态同步
状态同步简单来说就是同步游戏中的各种状态,当客户端发送游戏动作到服务器,服务器接收到之后,通过计算游戏行为的结果,然后广播下发给客户端游戏中的各种状态数据。客户端接收到状态数据后显示内容。这种做法类似于各个客户端都在远程操作服务器上的软件。例如最高的mud,以及日后大量的国产网游,特别是回合制游戏,大多采用这种方式。
状态同步的流程:
为了给游戏玩家更好的体验,减少同步的数据量,客户端也会做很多的本地运算,减少服务器同步的频率以及数据量。
状态同步其实是一种不严谨的同步,它的思想中不同玩家屏幕上的一致性的表现并不是重要指标,只要每次操作的结果相同即可。所以状态同步对网络延迟的要求并不高。例如:RPG游戏中200~300ms的延迟对用户来说是可以接受的,但在RTS(即时战略)游戏中50ms的延迟却会很受伤。
帧同步
帧同步是RTS游戏经常采用的一种同步技术,状态同步中数据量会随着需要同步的单位数量增长,而对于RTS来讲动不动就是几百个单位可以被操作,如果这些都需要同步的话,数据量是不能被接受的,所以帧同步不同步状态,之同步操作。例如游戏中同步玩家的操作指令,操作指令包含当前的帧索引。
简单来说,客户端发送游戏动作到服务器,服务器接收并汇总,然后直接转发给所有客户端,或者客户端直接通过P2P技术发送。客户端根据收到的游戏动作来做运算和显示。这种做法等于客户端之间相互远程控制其他客户端上的游戏软件。早期的ipx网络游戏,例如红色警戒、帝国时代、星际争霸,以及大量支持网络连线双打游戏机模拟机,都是采用这种方式。
那些游戏需要使用帧同步呢?
帧同步的流程
帧同步主要依赖客户端的能力,服务器仅仅是做一个转发,甚至客户端可以无需服务器,通过P2P方式来转发数据。由于只是转发游戏的行为,所以广播的数据量比状态同步要小很多。非常适合游戏行为非常频繁的动作游戏,诸如飞行射击、FPS、RTS(即时战略)。
状态同步由于要把整个游戏的状态都广播下去,如果游戏中的对象特别多,比如满屏的子弹、怪物,那么要广播的数据量就会很大,这个时候帧同步的优势就比较明显,因为不管有多少”机器控制的角色“,仅仅需要广播玩家角色有关的操作即可。反过来,如果游戏中有大量玩家同时聚集,那么帧同步和状态同步的差异就不太明显。反而状态同步能得到更多安全性,因为游戏运算在服务器上,比较容易防止外挂。
简单来说,帧同步技术最要的概念是”相同的输入 + 相同的时机 = 相同的显示“。也就是说,游戏接收来自网络的多个客户端的操作,如果这些操作在各个客户端上都是一样的,那么多个客户端的显示也就是一样的,进而带来了”同步“的效果。在这种情况下,各个客户端的运算要绝对一致,不能依赖诸如本地时间、本地随机等”输入“,而要一切以网络来的数据为主。
因为帧同步的特性,因此很容易做出战斗回放,即服务器记录所有操作,客户端请求到操作文件再执行一次。帧同步的特性导致客户端的逻辑实现和表现实现必须完全分离。
帧同步的目的在于消除网络波动性带给玩家的卡顿以及忽快忽慢的不良体验。
状态同步和帧同步的比较和选择
对于单位比较多的即时策略游戏,帧同步是很好的选择。相反的,如果玩家比较多,状态同步则更加合适,因为安全性更高。一般大型MMOARPG都采用状态同步,由于状态同步采用C/S架构,所有状态由服务器来控制,安全性比较高,但流量比较大。帧同步采用的是囚徒模式,所有C端强制采用一个逻辑帧率,从而保证输出一致,其特点是流量小,安全性较差。
囚徒模式又叫锁步模式,就是把所有参与对战的客户端看成排成一列的囚犯,这些囚犯们的左脚都被锁链给连起来,如果要往前走,就只能同时迈步,如果其中某个人走快了或走慢了,都回让整队人停下来。
帧同步是一种对同步源进行像素级同步显示的处理技术,对于网络上的多个接入者,一个信号将会通过主机同步发送给其他人,并同步显示在各个终端上。同步信号可以是每帧的像素数据,也可以是影响数据变化的关键事件信息。
帧同步在网络游戏应用中的设计有别于传统的MMORPG游戏,因为可以承载大量的后台计算,实现类单机的效果,所以可以在射击类、飞行类游戏中实现弹幕计算或格斗类的高精度打击效果。
什么叫做帧同步呢?服务器收集客户端手机发送过来的操作,然后在特定的时间(收集完成之后),再广播发送给每个客户端。客户端根据接收到的输入,进行同样的逻辑处理,最终得到同样的结果的过程。在实现上,一般都是以服务器按固定的帧率,来搜集每个客户端的输入,然后把这些输入广播给所有客户端。由于每个操作指令到达所有客户端的时间(帧)都是一样的,所以每个客户端运算的结果也是一样的,也就是同样的输入就会得到同样的结果。
这就好像是玩家通过网络将操作手柄连接到你的手机,这种同步方案是传统单机局域网游戏中最常见的。
帧同步模型最大的优点在于强一致性,每个客户端的表现是完全一样的,非常适合高度要求操作技巧的游戏。由于广播的仅仅是玩家的操作,所以数据量很少。不管游戏中的角色数量、状态数量有多大多复杂,都不会影响广播的数据量。
帧同步模型最大的缺点是对所有玩家的延迟都有要求,一般来说要求在50毫秒以内,如果有一个客户端网络卡住了,所有客户端都要停下来等待。
另外在帧同步模式中,数据同步的频率较高,网络延迟越小越好。由于TCP的滑动窗口机制和重传机制,导致延时机制,导致延时无法控制。因此帧同步一般采用UDP进行网络传输,但UDP又会衍生出可靠性问题,对于客户端,如果某些UDP包没有收到,就会出现丢帧的情况。
客户端A的操作A1与客户端B的操作B1,共同封装成OperateCmd数据发送给PVP服务器,PVP服务器每66毫秒产生一个逻辑祯,在该桢所在时间段内,收到A1和B1后,生成一个Frame数据块,在该帧时间结束时,将Frame发送给客户端A和B。Frame数据块内有该帧的帧号,客户端A和B接收到Frame数据后,便知道该帧内,客户端A和客户端B都做了什么操作。然后根据接收到的消息A1和B1进行游戏表现,最终呈现给玩家A和B的结果是一致性的,从而实现客户端A和B的数据同步。
帧同步既然是在特定时间发送,也就是说每隔一段时间收集用户操作指令,那么要间隔多久内。例如每隔一段时间搜索用户的操作。此时,如果时间太快则网络速率达不到要求,如果时间太长则用户操作不流程。哪里多少才比较合适呢?根据统计玩家至少要在50ms 100ms可以完成一次,一般维持到15 20次左右会比较安全。
状态同步简单来说就是有一个权威服务器运行着一个没有图形界面的客户端,然后服务器收集所有人的操作数据 计算后再把所有人的关键数据广播给所有人,玩家的客户端只是服务器的一个展示。 缺点是有些情况下同步数据量会很大 因为计算全在服务器所以可能压力会比较大。 帧同步中的每一个客户端都是要计算所有数据,服务器只需要转发彼此的操作即可。 帧同步的同步过程: 1.收集所有人的输入,广播给所有人。 2.客户端接收到所有人的输入,客户端本地开始根据输入计算得到游戏结果。 优点 服务器压力小,同步的数据量也很小相对应的可以有更低的延迟和带宽占用,可以直接没有服务器。天生支持录像。 缺点 反作弊难度较大,所有数据都在客户端本地。 如果要做帧同步 就必须保证所有客户端再执行相同操作的情况下的结果必须百分百一样,这样我们就不可以使用Unity自带的物理引擎。(亲测 会不同步) 因为不同cpu和操作系统可能float的精度也不同 所以也要避免使用float。(虽然说float有固定标准的,按理来说现在不同平台已经都一样了,但是谨慎起见我还是没用float) 帧同步的核心逻辑也不可以写在Unity脚本的生命周期里 例如Update 首先要区分 逻辑帧和渲染帧。 我们同步的是逻辑帧,所有位移和伤害判定什么的也都是在逻辑帧中,渲染帧中做平滑处理。 Unity中的帧就可以当作是渲染帧。 每次Update就是一个渲染帧,每次FixedUpdate就可以当作是逻辑帧。 渲染帧是没有固定间隔的 性能高刷的就快间隔就短。而逻辑帧是必须固定间隔的。 我两台手机要创建房间进行游戏。 服务器接收Input数据 服务器广播Input消息 上面的例子中 服务器的那台机器 如果渲染帧卡了一秒 而逻辑帧1秒20帧 ,那么就直接一个渲染帧中调用20次逻辑帧 追赶上进度。 如果服务器卡住了 所有人也都会同步暂停。 如果你有需要 也可以做主机迁移 随时接替原来的主机 防止房主掉线 大家一起掉线。 无论帧同步还是状态同步理论上来说都要做预测回滚,状态同步做这个还好做一点。 预测回滚基本就是按照上一次的操作客户端自动多模拟一帧或者几帧 来抵消网络延迟的感觉,但是如果预测结果和之后真实发生的结果不符的时候 就需要回滚客户端到正常的结果上 然后再次预测。 (如果一个人在游戏里 反复左右移动 比如CS里对枪时 疯狂ADADADADAD左右移动 这种情况下 如果有客户端有预测回滚 就会疯狂的预测错误而回滚 客户端也会增加额外的计算压力) 预测回滚因为我自己做的效果很不好 大概如下图一样,所以我就不讲具体怎么做了。 (英雄联盟的预测回滚做的也不咋样,设置里面有个预测选项默认是关闭的 手动勾选打开之后 就算网络正常效果也跟下图一样。) 预测回滚的方案很多 并不是只有一种,像《战地3》的预测回滚就特别魔性 你如果击中敌人了 但是因为延迟导致服务器判定没击中,但是你客户端已经提示击中了 再对其他人影响不大的情况下 它会让其他所有玩家和服务器陪着他一块回滚 让子弹打中那个人。。。。 (难道这就是我快速躲进掩体里之后还被打死的原因?)。 玩家每一逻辑帧执行结束之后 把所有角色的关键数据加密为MD5 上传服务器,服务器进行比对。如果是所有人上传上来的MD5都一样 说明所有人的游戏结果都是同步的,如果有人修改了血量那么就会造成游戏不同步 自己的MD5和其他人的不一样,服务器可以强行纠正它 或者 踢掉它。 游戏结束之后上传整场比赛左右的操作数据,服务器开一个客户端 一瞬间跑完所有操作所有帧 看最终的结果与客户端上报上来结果是否一致,如果不一致肯定有人作弊了。 像透视 自瞄这种 本质上没有改变游戏数据的作弊 就不太容易检测。这里我根据自己的理解和经验对比一下帧同步和状态同步的主要区别以及各自的优缺点。帧同步我没有使用过,在具体的理解上可能会有偏差。
服务器负责转化客户端的操作,每个客户端在固定的逻辑帧执行该帧所有客户端的操作命令,通过在严格一致的时间轴上执行同样的命令序列得到同样的结果。主流的老牌RTS游戏都是帧同步:星际争霸、war3
优点 :
缺点 :
服务器承载所有计算,客户端只做表现。主流的大型MMO游戏都采用状态同步。
缺点 :
无论是状态同步还是帧同步,对于网络延迟的优化都会涉及到的问题是:
欢迎分享,转载请注明来源:夏雨云
评论列表(0条)