Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

2.3 强实时对战型游戏问题模型

强实时对战游戏在房间制游戏的基础上增加了极端的延迟约束——操作响应必须在百毫秒内,否则体验严重劣化。这带来了一系列连锁的技术挑战。

典型游戏:FPS(CS:GO、守望先锋、Valorant)、MOBA(英雄联盟、DOTA2、王者荣耀)、大逃杀(PUBG、Apex Legends、堡垒之夜)。

为什么低延迟是核心挑战?

强实时游戏的网络延迟要求来自人类感知的物理极限:

  • 100ms 以下:玩家感觉流畅,操作“跟手“
  • 100-200ms:玩家开始感觉到“不跟手“,高手尤其明显
  • 200ms 以上:所有玩家都能感知延迟,体验显著劣化

而且这个延迟是端到端的:玩家操作 → 客户端发送 → 网络传输 → 服务器处理 → 网络传输 → 客户端渲染。每一环都要争分夺秒。

参考:Kjetil Raaen 在博士论文中通过实验测量了不同游戏类型的延迟容忍度,结论是 FPS 和格斗游戏对延迟最敏感,100ms 是体验分水岭。 — Kjetil Raaen, “Response Time in Games”, http://home.simula.no/~paalh/students/KjetilRaaen-phd.pdf 1

四个核心技术问题

问题1:用什么传输协议?

为什么 TCP 不适合强实时游戏?

TCP 的设计目标是可靠、有序传输。它有两个机制与强实时游戏的需求冲突:

  1. 重传机制:丢包时,TCP 会重传丢失的包,并缓存后续包直到丢失的包恢复。这意味着一个丢包会导致后续所有包的延迟尖刺(Head-of-Line Blocking)。对于游戏来说,旧的状态已经没用了,你需要的是最新的状态,而不是重传旧状态。

  2. 拥塞控制:TCP 会自动降低发送速率来应对网络拥塞。但游戏数据的发送速率是由游戏逻辑决定的(每 tick 一次),不能因为 TCP 觉得网络拥塞就停止发送。

所以强实时游戏几乎都选择 UDP,然后在 UDP 之上按需实现自己的可靠性机制:

  • 不需要可靠传输的数据(位置更新、动画状态):丢了就算了,下一帧会有新的
  • 需要可靠传输的数据(击杀事件、技能释放):自己实现轻量级的 ACK + 重传,但不阻塞其他数据

KCP 是国内游戏行业广泛使用的方案,它在 UDP 之上实现了类似 TCP 的可靠性,但牺牲了一定的公平性来换取更低的延迟。

参考:Glenn Fiedler 在 Gaffer On Games 系列文章中详细解释了为什么游戏应该用 UDP 而非 TCP,以及如何在 UDP 上构建游戏所需的可靠性机制。 — https://gafferongames.com/categories/game-networking/ 2

问题2:如何同步状态——帧同步 vs 状态同步?

这是强实时游戏最核心的架构决策。两种模型有本质区别:

状态同步(State Synchronization / Authoritative Server)

  • 服务器运行完整的游戏模拟
  • 客户端只发送操作输入
  • 服务器计算结果后,把状态广播给客户端
  • 客户端只负责渲染

优点:天然防作弊(服务器权威),客户端实现简单 缺点:服务器计算压力大,带宽消耗大(需要发送完整状态),对服务器延迟敏感

帧同步(Lockstep / Deterministic Simulation)

  • 所有客户端各自运行完整的游戏模拟
  • 每一帧,所有客户端交换操作输入
  • 因为模拟是确定性的(相同输入 = 相同结果),所以结果一致
  • 服务器只是中继输入

优点:带宽消耗小(只传输入),服务器计算压力小,回放简单(只需记录输入) 缺点:要求严格的确定性浮点运算(实现困难),一个客户端卡住会拖慢所有人(传统 Lockstep),作弊风险更高

参考:帝国时代的 “1500 Archers on a 28.8” 是帧同步的经典论文。它创造性地用“滑动窗口“解决了传统 Lockstep 的等待问题。 — Mark Terrano, Paul Bettner, GDC, https://zoo.cs.yale.edu/classes/cs538/readings/papers/terrano_1500arch.pdf 3

参考:Ruoyu Sun 的 “Game Networking Demystified, Part I: State vs. Input” 清晰地对比了两种模型的本质区别——不是“传什么数据“的区别,而是“谁来做计算“的区别。 — https://ruoyusun.com/2019/03/28/game-networking-1.html 4

如何选择?

因素选状态同步选帧同步
作弊防护要求高✅ 服务器权威❌ 客户端运行逻辑
物理模拟复杂✅ 服务器统一计算❌ 确定性浮点困难
回放需求需要记录完整状态天然支持(只记录输入)
服务器成本高(要跑模拟)低(只做中继)
单局人数多可能更好(服务器控制带宽)Lockstep 等待问题严重
跨平台(PC/手机/主机)✅ 客户端只需渲染❌ 各平台确定性浮点一致

实际上很多现代游戏采用混合方案——关键逻辑用状态同步(服务器权威),部分效果用确定性模拟(客户端计算)。守望先锋就是一个著名的混合案例。

参考:守望先锋的网络架构在 GDC 和 SIGGRAPH 上有多篇分享。Tim Ford 在 GDC 2017 的演讲 “Overwatch Gameplay Architecture and Netcode” 描述了其网络代码架构。注意:具体的架构细节应以 Blizzard 官方发布的内容为准。 — 相关 GDC 演讲可通过 GDC Vault 搜索 5

问题3:如何掩盖延迟——客户端预测与服务器回溯

即使网络延迟优化到了极致,物理延迟仍然存在(如北京到上海的光纤延迟约 10-15ms,到美国约 150ms)。因此需要技术手段来掩盖延迟的体感

客户端预测(Client-Side Prediction)

核心思想:客户端在发送操作的同时,立即在本地模拟操作结果并渲染,不等服务器确认。

例如玩家按“向前走“:

  1. 客户端立即在本地移动角色(预测)
  2. 同时发送操作给服务器
  3. 服务器计算后返回确认状态
  4. 客户端对比预测和确认——如果一致,无缝继续;如果不一致,纠正并重新预测

这是 Glenn Fiedler 在 “What Every Programmer Needs to Know About Game Networking” 中描述的经典模式。最早由 QuakeWorld 引入。

参考:Glenn Fiedler, “What Every Programmer Needs To Know About Game Networking” — https://gafferongames.com/post/what_every_programmer_needs_to_know_about_game_networking/ 6

服务器回溯(Lag Compensation / Server Rewind)

核心思想:当服务器收到玩家的射击操作时,考虑该操作到达服务器的网络延迟,将游戏世界**“倒退“到玩家按下按钮那一刻的状态**,在那个状态下判定是否命中。

举例:玩家 A(延迟 50ms)在 t=100ms 时射击玩家 B。数据到达服务器时是 t=150ms。如果直接在 t=150ms 的状态判定,B 可能已经移动了。服务器回溯的做法是:在 t=100ms 的历史状态中判定是否命中。

这个机制由 Valve 在 Source 引擎中实现并公开文档化。

参考:Valve, “Lag Compensation”, 详细描述了服务器端如何保存历史状态快照、如何回溯、以及回溯深度(通常是 0.5-1 秒)。 — https://developer.valvesoftware.com/wiki/Lag_Compensation 7

实体插值(Entity Interpolation)

核心思想:客户端收到的是离散的状态快照(如 20Hz 或 30Hz),但渲染需要 60fps。在两个快照之间做平滑插值。

这引入了一个恒定的额外延迟(通常是 100ms),即客户端渲染的是“过去“的状态,但换来的是平滑的运动表现。

问题4:如何防止作弊?

强实时游戏 + 服务器权威 = 天然的作弊防护基础。但仍然需要关注:

  • 透视(Wallhack):服务器只发送玩家可见范围内的其他玩家状态(利用 AOI),减少信息泄露
  • 自瞄(Aimbot):服务器端做射击判定(而非信任客户端),加上行为分析检测异常瞄准模式
  • 速度外挂:服务器验证移动速度是否超过合理范围
  • 封包篡改:通信加密 + 关键操作签名

参考:Valve 的 “Source Multiplayer Networking” 文档中描述了 Source 引擎如何限制发送给每个客户端的实体数据(PVS - Potentially Visible Set),这是防透视的基础机制。 — https://developer.valvesoftware.com/wiki/Source_Multiplayer_Networking 8

架构总览

客户端                    服务器
  │                        │
  ├── 发送操作输入 ────────▶│
  │   (UDP, 高频)          │
  │                        ├── 运行游戏模拟
  │                        ├── 判定(含回溯)
  │                        │
  │◀───── 状态快照 ────────┤
  │   (UDP, 按tick)        │
  │                        │
  ├── 本地预测             │
  ├── 收到快照后纠正       │
  └── 插值渲染             │

注意延迟的来源和补偿手段如何配合:

  • 网络延迟 → 客户端预测来掩盖
  • 状态同步频率低 → 插值来平滑
  • 对方移动不可预测 → 服务器回溯来保证判定公平

小结

  1. 传输协议:强实时游戏用 UDP,不使用 TCP(避免 Head-of-Line Blocking 和不可控的拥塞控制)
  2. 同步模型:状态同步(服务器权威)vs 帧同步(确定性模拟),各有适用场景,现代游戏趋向混合方案
  3. 延迟掩盖三件套:客户端预测 + 服务器回溯 + 实体插值。三者协同工作
  4. 防作弊:服务器权威判定是基础,AOI 限制信息泄露是关键补充

下一节(2.4)将学习:持续在线世界型游戏问题模型,了解 MMORPG 的 AOI 和分片技术。


参考文献


  1. Kjetil Raaen, “Response Time in Games: Requirements and Improvements”, Simula Research Laboratory, http://home.simula.no/~paalh/students/KjetilRaaen-phd.pdf

  2. Glenn Fiedler, “Game Networking” 系列文章, https://gafferongames.com/categories/game-networking/

  3. Mark Terrano, Paul Bettner, “1500 Archers on a 28.8: Network Programming in Age of Empires and Beyond”, GDC, https://zoo.cs.yale.edu/classes/cs538/readings/papers/terrano_1500arch.pdf

  4. Ruoyu Sun, “Game Networking Demystified, Part I: State vs. Input”, https://ruoyusun.com/2019/03/28/game-networking-1.html

  5. Tim Ford (Blizzard), “Overwatch Gameplay Architecture and Netcode”, GDC 2017, GDC Vault

  6. Glenn Fiedler, “What Every Programmer Needs To Know About Game Networking”, https://gafferongames.com/post/what_every_programmer_needs_to_know_about_game_networking/

  7. Valve, “Lag Compensation”, https://developer.valvesoftware.com/wiki/Lag_Compensation

  8. Valve, “Source Multiplayer Networking”, https://developer.valvesoftware.com/wiki/Source_Multiplayer_Networking