这里我根据自己的理解和经验对比一下帧同步和状态同步的主要区别以及各自的优缺点。帧同步我没有使用过,在具体的理解上可能会有偏差。

帧同步:

服务器负责转化客户端的操作,每个客户端在固定的逻辑帧执行该帧所有客户端的操作命令,通过在严格一致的时间轴上执行同样的命令序列得到同样的结果。主流的老牌 RTS 游戏都是帧同步:星际争霸、war3

优点

  1. 开发方便,可以无视客户端服务器(但是要考虑逻辑和表现分离)
  2. 打击感反馈好,例如所有的命中都能在本地马上触发相应的扣血和打击表现,反馈及时准确,无须像状态同步那样等待服务器推送扣血或者向服务器请求扣血。
  3. 网络流量小,这个会带来很多好处:带宽费用小、用户成本低、降低收发包带来的耗电(据说比较可观)

缺点

  1. 对网络要求高。这个涉及到具体帧同步实现的方式。
    锁帧问题,服务器会等待所有的客户端的第 N 帧操作都到齐之后再发送到各客户端第 N 帧的操作,这样一旦有一个客户端网络波动,所有人都会卡住。war3 的做法是加入了超时机制,如果在第 N 帧超时没有收到某个客户端第 N 帧的操作,就不再等待这个客户端的这帧操作,并认为该客户端在这帧什么都没做。但是如果这个客户端只是延迟很高,他所有的操作是否都会被服务器判定无效呢?
    逻辑帧平滑问题,一般收到的逻辑帧命令数据会加入客户端正在顺序执行的逻辑帧的队列中。如果队列设置过长,操作延迟就会比较高;如果队列很短,在网络波动时,就会出现队列为空饥饿状态,造成逻辑帧不平滑。这个可以采用逻辑和表现分离、平滑插值等做法。逻辑和表现分离做的比较好的话可以做到无 buffer。平滑插值是一些表现的过渡处理,比如卡顿感一个很主要的来源是怪物移动的不平滑,一个比较好的应对方法是以怪物方向为主计算位置,即使没有逻辑帧,表现帧也会继续根据当前方向速度计算位置,这样即使延迟出现波动时也不会出现位移的不平滑。
  2. 反外挂能力差,容易本地修改,开图,修改属性等。
  3. 断线重连需要追帧
  4. 客户端逻辑计算性能压力大,需要每逻辑帧计算所有游戏单位的逻辑状态,即使单位不在屏幕内。
  5. 对结果一致性控制比较严格,如果使用了第三方的库,需要能够控制结果的一致性。其他因素包括浮点计算在不同平台的误差差异、随机数序列一致性、一些容器的访问顺序问题。

状态同步:

服务器承载所有计算,客户端只做表现。主流的大型 MMO 游戏都采用状态同步。

优点

  1. 容易断线重连
  2. 容易防外挂
  3. 简单粗暴

缺点

  1. 流量大
  2. 打击感反馈匹配不够精准,因为所有的表现都是服务器推送的,在网络波动、客户端服务器不同计算的误差下,客户端各个表现比较难契合。
  3. 对网络要求也会比较高,如果 2 中说的各个表现的契合,以及位移等都会受到网络波动的影响。

无论是状态同步还是帧同步,对于网络延迟的优化都会涉及到的问题是:

  1. 在网络协议层优化,可靠 UDP 代替 TCP,降低延迟
  2. 在表现上优化,客户端先行、平滑插值等在表现上降低对延迟的感受