Post

状态同步和帧同步

Predictive and Lockstep

状态同步(Predictive)和帧同步(Lockstep)是两种比较常用的网络同步技术,主要用于多人在线游戏中,以确保所有参与者在同一时间看到相同的游戏状态。主要涉及到不同玩家视界之间的互相影响,包括碰撞,技能效果,伤害,移动,属性变化等等。

由于一直学习的是后台的技术,对状态同步了解更多一点,对帧同步了解比较少。这里学习了解一下两种同步机制的原理和使用场景。

状态同步

状态同步是一种不那么实时同步的方式。客户端会预测其他玩家的状态,并在接收到实际的状态后进行校正。这种同步方式容忍其他客户端的网络时延,等待其他玩家的信息同步时可以继续进行计算和渲染。

基本原理和特点

基本原理:

  • 状态同步的战斗逻辑在服务端;
  • 在状态同步下,客户端更像是一个服务端数据的表现层
  • 一般的流程是:
    • 客户端上传操作到服务器,
    • 服务器收到后计算游戏行为的结果,然后以广播的方式下发游戏中各种状态,
    • 客户端收到状态后再根据状态显示内容。

这种实现上,客户端使用RPC协议向服务器发送各种指令,服务器向客户端同步各种角色属性状态等信息。这种设计有几个可能的问题:

  • 延迟比较大,需要等待服务器计算好状态。对于客户端可能性能过剩,对于服务器可能压力过大;
  • 对象少的游戏,可能造成较大带宽浪费。

应用和案例

典型的使用状态同步的游戏类型有SLG、绝地求生这几类游戏。

SLG

此类游戏有一个大世界地图,且每个地图服务器上有大量玩家,无法使用帧同步,否则会导致巨大的游戏时延。服务器向每个玩家在同步其自身状态的同时,还会同步其视界范围内的信息(全服信息无法完全同步,太多了)。

只同步视野范围内信息的实现可以参考AOI(Area Of Interest),根据玩家位置,维护一个动态的视野列表,视野外的对象会被完全忽略。实现方式有很多,常见的是基于格子的空间划分算法。

PUBG

绝地求生的玩家数量每局有100个人,因此无法进行所有人状态之间的帧同步,会造成很大的延迟。

LOL

LOL为了防止开挂作弊,以及保证玩家游戏体验,使用状态同步的方式开发。玩家局内的属性,技能效果等都由服务端进行计算。

2011年的时候,LOL官方还(很装地)出了一个50000QB悬赏外挂的公告,虽然游戏局内没有bug,但是局外进游戏的时候设置天赋这些出现了bug。再后来,英雄联盟盒子修改皮肤,无限视距篡改客户端,因为英雄联盟客户端游戏局内并没有把这些东西做强限制绑定(不过后面出补丁了,篡改客户端封号)。

帧同步

帧同步(Lockstep)是一种严格同步的方式,LockStep意为锁步。所有客户端在每一帧都必须等待其他客户端的输入,然后再进行计算和渲染。这种方式确保了所有客户端在每一帧都拥有相同的状态。

基本原理和特点

  • 帧同步的战斗逻辑在客户端;
  • 在帧同步下,通信就比较简单了,服务端只转发操作,不做任何逻辑处理;
  • 客户端按照一定的帧速率(理解为逻辑帧,而不是客户端的渲染帧)去上传当前的操作指令,服务端将操作指令广播给所有客户端;
  • 当客户端收到指令后执行本地代码,如果输入的指令一致,计算的过程一致,那么计算的结果肯定是一致的,这样就能保证所有客户端的同步,这就是帧同步;

帧同步有几个可能的问题:

  1. 如果服务器没有验证,完全由客户端处理玩家操作指令的逻辑,很容易设计外挂篡改客户端(加速,透视,修改客户端参数等);
  2. 由于每一个逻辑帧需要等待其他客户局端的指令,如果有玩家网络延迟会是的原先的帧锁住(即Lockstep),网络较差的客户端可能会影响其他玩家的游戏体验;
  3. 不同机器的浮点数精度,随机数值计算不统一,可能造成玩家之间不同步;

应用和案例

Dota

Dota 2使用的是状态同步,但Dota使用的却是帧同步。

对比

  1. 主要区别在于战斗核心逻辑写在哪里,状态同步的战斗逻辑在服务端,帧同步的战斗逻辑在客户端;
  2. 状态同步服务器开发复杂,客户端开发简单,帧同步反之;
  3. 帧同步适合于少量玩家,状态同步则不作要求;
  4. 帧同步不适合跨平台,状态同步适合,因为状态同步不依赖不同客户端设备需要产生相同的计算结果,因为计算在服务端进行;

网络协议

如果说,我要偷懒点的话,开发上全部选用TCP就可以了。但是TCP的传输有时候需要进行繁琐的确认和重传机制,速度会远远不如UDP;而使用UDP的话,则需要在自己业务层进行数据的确认和重传机制的实现。幸运的是,TCP现在可以选择打开NODELAY选项,大部分情况下网络性能尚可。而且随着现代网络基础设施的健全,大部分人的网络环境很好,没必要搞太复杂的网络设计,引进新的开发负担和运行维护风险。

This post is licensed under CC BY 4.0 by the author.