什么是网络同步

网络同步是指通过网络将数据从一个系统或节点传输到另一个系统或节点,并保持两者之间的数据一致性。换句话说,游戏中的网络同步就是把我的状态同步给远程玩家看到的“我”的镜像,使双方在屏幕上看到的效果是一致(或接近一致)的。

在常见的多人联机游戏(例如下棋、格斗、fps等等)中,网络同步是非常重要的一项需求。游戏中的玩家需要时时刻刻了解其他玩家的状态或者行为,才能辅助自己做出下一步决策(例如是否开枪等)。

如何知道其他玩家的状态,又如何让其他玩家知道我的状态呢?这时候就需要网络同步技术了。

同步设计目标

同步设计主要有两个目标,即 一致性及时性 。一致性指多个客户端看到的效果是一致的,而及时性指能否及时完成网络同步。在实际工程中我们往往很难同时满足一致性和及时性,这是因为网络延迟始终存在,客户端在接收到最新状态前只能对其他玩家镜像的状态进行预测(通常会采用一些客户端障眼法,例如插值)。

一致性及时性 这两个核心目标下,我们可以拆解出三个子设计要素(公平、体验和开销),根据实际情况进行优先级权衡。一般来说用户体验是位于首位的。

公平性

  • 确定
    操作具有幂等性,即玩家执行一个操作所得的的结果是确定而非随机的。游戏存在明确的规则,玩家知道规则带来的确切的后果,这样才可以基于规则进行博弈。

  • 安全
    数据的安全性代表玩家的数据隐私不应该被第三方破坏或篡改。当计算放在客户端时,数据就很容易被篡改(作弊行为)。

用户体验

  • 延迟
    由于网络原因,延迟很难避免。其中延迟又分为输入响应延迟状态延迟

    • 输入响应延迟
      影响操作手感,输入响应延迟对存在QTE判定(例如格斗游戏)等输入敏感类游戏影响巨大。
    • 状态延迟
      影响判断,例如 fps 游戏中需要根据状态判断玩家是否成功击杀对方等。
  • 稳定
    由于网络环境不稳定,可能发生抖动丢包,这将引起游戏中的“顿挫感”与“拉扯感”(当然,这也可能是由于GC造成的)。网络环境中断时会引起游戏断线,这时客户端会触发断线重连的尝试,尝试一定次数后判断为连接服务器失败。
    王者荣耀中的断线重连

成本开销

  • 流量
    流量代表客户端需要收发多少数据,流量越大越可能遇到网络问题(例如丢包),并对用户的话费造成影响(流量开销变大了,需要上传和下载的东西变多),同时造成运维成本上升。

  • 计算量
    计算量越大对客户端的负载越大(如果采用的是帧同步),越容易造成手机发烫、电池消耗大等问题。

  • 研发成本
    实现不同的同步算法的技术门槛和维护成本是不一样的,在下文中会详细说明。

网络同步方案

在网络同步中,我们一般要传输什么数据呢?在实际生活中,一款游戏可以被拆成“输入-逻辑处理-输出”三个部分:

  1. 用户通过键鼠/触摸屏等设备对游戏产生输入;
  2. 输入经过游戏的核心逻辑处理模块处理;
  3. 处理完后将状态输出到屏幕上,最后呈现在用户面前。

那么很明显,我们需要同步的就是用户的输入操作、或者这些操作所产生的一系列事件,并将这些事件同步到其他玩家的客户端上,这样其他玩家的客户端就可以根据同步过来的输入事件类型计算出对应用户的状态并呈现在其他玩家的游戏中。这个思路实际上就是帧同步的思想。

当然,我们也可以直接同步用户的输入操作经过计算后得到的状态,这样就省去了其他玩家客户端上对输入事件的计算工作。这个思路实际上就是状态同步的思想。

帧同步和状态同步都是保持网络同步中“一致性”的方法,让我们在之后的文章中展开说说吧。

方案对比

回到前文的“同步算法设计七大要素”,我们可以先对比一下帧同步与状态同步在这七大要素中的表现情况:

公平

  • 确定
    • 帧同步:具有强一致性
    • 状态同步:非本地仲裁的数据有延迟或需要修正
  • 安全
    • 帧同步:输入数据和状态数据可能被篡改,拥有所有玩家的状态,隐私问题难以保障。
      在这种情况下,服务器需要进行完整逻辑校验,并对关键状态进行校验(投票)。
    • 状态同步:本地的输入数据和状态数据可能被篡改,远端的状态数据是隐私的。
      对延迟敏感的项目,可以本地维护状态、服务器后校验;对延迟不敏感的项目,可以直接通过服务器维护状态。

体验

  • 延迟
    • 帧同步:网络优化,采用RUDP
    • 状态同步:对网络抖动不敏感,可用RUDP也可用TCP
  • 稳定
    • 帧同步:断线重连非常复杂,需要服务器缓存所有帧数据,发回给客户端,从断线处开始播放到当前帧
    • 状态同步:可以由服务器保存当前状态,重连时使用该状态即可

开销

  • 流量
    • 帧同步:同步指令,同步流量小
    • 状态同步:同步状态,同步流量大
      可以通过优化编码格式、设置电平触发/边沿触发(是每秒发送按键,还是在按键变化时发送?)、区分重要/不重要数据的方式优化流量开销。
  • 计算量
    • 帧同步:计算量全部集中在客户端(因此无法维护大规模的游戏)
    • 状态同步:部分计算量在客户端(本地状态),部分计算量在服务端
  • 研发成本
    • 帧同步:技术门槛高、维护成本高、研发周期短
    • 状态同步:技术门槛低、维护成本高(随着状态复杂而复杂化)、研发周期长

以下是不同的同步方案适用的游戏类别,可以带着印象看后续的文章。

游戏类型 最适用方案 原因
射击(FPS/TPS) 分布式状态同步 对实时性要求高,要求玩家能立马看到结果(及时反馈),单局规模可能比较大
即时战略(RTS) 帧同步 需要同步同屏中的大量单位,采用帧同步只需要同步小部分操作指令
多人竞技(MOBA) 帧同步 对公平性要求较高、对误差要求高,帧同步可以保证多个客户端的误差很小
多人角色扮演(MMORPG) 服务器状态同步 角色数量多,对反作弊要求高
休闲房间(棋牌) 帧同步/服务器状态同步 实时性要求低、反作弊要求高。如果需要同步大量单位可以考虑帧同步

参考资料

百万在线:大型游戏服务端开发(罗培羽)
https://gameinstitute.qq.com/course/detail/10242