Apollo 技术文档Apollo 技术文档
指南
  • 架构概述
  • BigWorld 架构深度解析
  • BigWorld 进程架构与玩家生命周期
  • AOI九宫格系统详解
  • AOI广播与消息去重
  • Base 模块
  • Core 模块
  • Runtime 模块
  • Data 模块
  • Network 模块
  • /modules/actor.html
  • Game 模块
  • BigWorld 模块
服务器应用
API 参考
QA
GitHub
指南
  • 架构概述
  • BigWorld 架构深度解析
  • BigWorld 进程架构与玩家生命周期
  • AOI九宫格系统详解
  • AOI广播与消息去重
  • Base 模块
  • Core 模块
  • Runtime 模块
  • Data 模块
  • Network 模块
  • /modules/actor.html
  • Game 模块
  • BigWorld 模块
服务器应用
API 参考
QA
GitHub
  • MMORPG 架构 QA

Q17: 什么是延迟补偿?应该补什么,不应该补什么?

核心结论

延迟补偿不是“把网络延迟消灭掉”,而是把延迟对体验和判定的破坏控制在可接受范围内。

它通常包含四类手段:

  • 本地玩家的客户端预测
  • 服务端权威校正
  • 远端实体的插值与有限外推
  • 命中判定中的历史回溯

真正需要先想清楚的不是“用了什么高级算法”,而是三件事:

  • 哪些结果必须由服务端最终裁定
  • 哪些内容允许客户端先显示再纠偏
  • 哪些玩法值得为低延迟体验付出复杂度

一、先区分状态同步与延迟补偿

状态同步解决的是“客户端怎么拿到服务端状态”,延迟补偿解决的是“网络往返存在时,怎么让操作看起来仍然及时、判定仍然公平”。

两者经常一起出现,但不是一回事:

  • 状态同步关注数据分发、频率、增量、快照、AOI
  • 延迟补偿关注预测、回滚、校正、回溯、插值

如果把这两件事混在一起讨论,方案很容易失焦。比如快照发得再勤,也不能自动解决本地操作手感;同样,预测做得再激进,也不能替代权威同步。

二、延迟补偿到底在补什么

1. 补输入响应

玩家按下移动、转向、施法、开火后,如果必须等服务端确认再显示,体验会非常迟钝。

因此常见做法是:

  • 客户端立刻执行本地预测
  • 同步把输入发给服务端
  • 服务端按权威规则重算
  • 客户端收到结果后做校正

这补的是“操作立即反馈”,不是把客户端变成权威源。

2. 补显示连续性

远端实体的位置更新总会晚于真实时间线。如果客户端直接显示最近一包数据,画面会抖动、跳变、瞬移。

因此常见做法是:

  • 客户端缓存最近几帧权威快照
  • 渲染时故意落后一个小缓冲窗口
  • 在两个权威点之间做插值

这补的是“视觉连续性”,不是提高真实判定精度。

3. 补命中判定公平性

射击、碰撞、技能命中这类玩法里,客户端看到的目标位置往往比服务端当前状态落后几十到几百毫秒。

如果服务端只按“当前帧目标位置”判定,玩家会频繁出现“明明打中了却没中”的体验。

因此很多实时玩法会做历史回溯:

  • 客户端把射击时刻、朝向、目标信息上传
  • 服务端回到该玩家发起操作时对应的历史状态
  • 在那个历史时刻做一次命中判定

这补的是“观察视角和服务端判定时间线不一致”的问题。

三、哪些内容适合补,哪些不适合

适合做预测或补偿的,通常满足两个条件:

  • 短时间内结果可逆或可平滑纠偏
  • 即使暂时显示错了,最终也能接受服务端校正

典型包括:

  • 自己的移动
  • 自己的朝向
  • 本地施法前摇或动作表现
  • 远端实体的位置与动画显示

不适合让客户端先做“最终判定”的通常包括:

  • 伤害结算
  • 资产变化
  • 掉落归属
  • 任务完成
  • 交易、拍卖、邮件等强一致操作

这些内容可以先播放反馈,但最终结果必须以服务端权威为准。

四、四类常用手段

1. 客户端预测

最常见的是移动预测。客户端先按输入模拟一小段位移,服务端再返回确认结果。

优点:

  • 手感直接
  • 对持续输入最有效

代价:

  • 必须有重放和校正机制
  • 预测逻辑与服务端逻辑不能偏差太大

2. 服务端校正

服务端确认状态回来后,客户端要决定怎么纠偏:

  • 小误差平滑插值回去
  • 大误差直接拉回
  • 对关键错误做硬校正

这里最忌讳两种极端:

  • 完全不校正,最后和权威状态越走越远
  • 每次都瞬移校正,画面不断抖动

3. 插值与有限外推

对其他玩家或怪物,通常不用预测输入,而是用插值隐藏抖动。只有在快照短暂丢失时,才做非常保守的外推。

原因很简单:

  • 远端实体没有本地输入可用
  • 激进外推一旦错了,反而比延迟更难看

所以工程上更常见的是“插值优先,外推兜底,时间很短”。

4. 历史回溯

这是射击或高速碰撞玩法的核心补偿手段。服务端需要保存一段时间的历史状态,例如最近 100ms 到 300ms 的位置、朝向、碰撞体信息。

流程通常是:

  1. 客户端上报操作发生时刻和输入参数
  2. 服务端找到该时刻附近的历史快照
  3. 重建相关实体的历史状态
  4. 用历史状态做命中或碰撞判定
  5. 再回到当前时间线继续运行

它解决的是“看见的目标”和“当前服务器状态”之间的时间差。

五、不同类型游戏的补偿重点不同

1. FPS / TPS

重点通常是:

  • 输入低延迟响应
  • 历史回溯命中
  • 高频位置同步
  • 严格限制校正跳变

因为这类玩法对几十毫秒的误差都很敏感。

2. MMORPG

重点通常是:

  • 本地移动流畅
  • 远端实体显示平滑
  • 技能表现及时反馈
  • 最终结果以服务端技能系统和战斗系统结算

这类玩法常常不需要把所有判定都做成 FPS 级别的回溯系统,否则成本过高,收益也未必匹配。

3. 帧同步类实时对战

这类玩法更依赖:

  • 输入收集
  • 锁步推进
  • 回滚或延迟输入处理

严格来说,这不完全是传统 MMO 状态同步体系里的“延迟补偿”,而是另一套以确定性仿真为中心的处理方式。

六、常见误区

1. 认为补偿越多越好

不是。补偿本质上是在体验、公平和复杂度之间做取舍。

补偿越激进,越可能带来:

  • 逻辑分叉
  • 纠偏闪烁
  • 被外挂利用
  • 服务端实现复杂度上升

2. 认为客户端看到什么就该判什么

也不是。客户端看到的是“经过延迟、插值、预测后的一份近似画面”,它更接近体验层,不等于权威真相。

3. 认为只有竞技游戏才需要补偿

不对。MMO 同样需要补偿,只是补偿重点不同。MMO 更强调移动、技能表现、AOI 内实体平滑;竞技射击更强调命中回溯和极低操作迟滞。

4. 认为延迟补偿可以掩盖所有网络问题

不能。高抖动、持续丢包、严重乱序、本地设备卡顿都会让补偿策略迅速失效。补偿只能改善体验,不能替代网络质量本身。

七、工程上通常怎么落地

一个相对稳妥的组合通常是:

  • 本地玩家移动做预测
  • 服务端维护权威状态
  • 远端实体采用插值显示
  • 命中敏感玩法按需做历史回溯
  • 大偏差做硬校正,小偏差做平滑校正
  • 所有资产与战斗结果仍由服务端确认

如果再往前走一步,还需要把下面几件事一起设计:

  • 快照频率和带宽预算
  • AOI 裁剪
  • 历史状态缓存窗口
  • 校正阈值
  • 异常网络下的退化策略

参考资料

  • Gabriel Gambetta, Fast-Paced Multiplayer
  • Glenn Fiedler, Snapshot Interpolation / Lag Compensation
  • Valve Developer Community, Lag Compensation
在 GitHub 上编辑此页
最后更新: 3/20/26, 6:06 AM
贡献者: cuihairu