十八、网络游戏的架构基础

18.1 同步算法

18.1.1 快照同步Snapshot

如Quake

  1. 步骤:
    1. 客户端:把输入发送给服务器
    2. 服务器:将所有客户的输入集合起来,在服务器中进行游戏世界的模拟,然后将游戏世界的状态生成快照返回给客户端
    3. 客户端:拿到服务器给的快照后,将所有对象设置为对应的状态,然后进行渲染
  2. 优点:
    1. 结构清晰,保证了绝对的一致性,无法作弊
    2. 不用担心同步的问题
    3. 客户端只负责输入和最后的渲染
    4. 当客户端非常多时,服务器的计算量是最低的,因为只需要对世界模拟一次即可
  3. 针对实际情况的改进:
    1. 服务器端的帧率通常会很低,需要客户端进行插值
    2. 快照可能包含非常多的信息,但是相邻两帧通常差距不大,因此可以只传delta,从而降低信息量
  4. 缺点:
    1. 浪费了客户端的算力
    2. 服务器生成快照传递给每一个客户端,会占用非常大的服务器处的上行带宽

18.1.2 帧同步Lockstep

如DOOM、王者荣耀

  1. 步骤:
    1. 每一帧:客户端把输入统一交给服务器
    2. 服务器等待所有服务器提交输入,然后把所有输入分发给客户端
    3. 客户端得到服务器的指令,做一致的游戏逻辑模拟,得到的结果一定相同
    4. 要求所有客户端进行初始化,初始条件必须相同
  2. 针对实际情况的改进:
    1. 如果有一个客户端发送输入总是很慢,就需要其他客户端等待它
      1. Bucket Synchronization:每隔固定的时间收集一次信息,服务器没收到的就当没发生
  3. 缺点:
    1. 一样的输入,得到的结果不一定相同,因为会有随机数、浮点数等不确定的因素
      1. 浮点数:要求满足IEE754标准
      2. 随机数:要求随机数种子、随机数算法严格相同

18.1.3 状态同步State Synchornization

如CS

  1. 步骤:
    1. 客户端:Authorized将命令发送给服务器(如向某个方向发射一个炮弹)
    2. 服务器:接收客户端的命令,模拟操作(如打中某个对象),然后将改变的状态广播给所有客户端
    3. 客户端:接收服务器的对场景状态的改变,模拟出整个世界
  2. 针对实际情况的改进:
    1. 客户端发送指令,服务器接受指令并确返回结果,会存在延迟
      1. Client-side prediction:客户端要进行预测操作,即先将客户的指令执行,然后再和服务器对齐
        1. 守望先锋:预测半个RTT+一个命令帧时间
      2. Server Reconciliation:预测与服务器的返回不一致时,客户端要与服务器对齐
        1. 平滑的差值对齐