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 的设计目标是可靠、有序传输。它有两个机制与强实时游戏的需求冲突:
-
重传机制:丢包时,TCP 会重传丢失的包,并缓存后续包直到丢失的包恢复。这意味着一个丢包会导致后续所有包的延迟尖刺(Head-of-Line Blocking)。对于游戏来说,旧的状态已经没用了,你需要的是最新的状态,而不是重传旧状态。
-
拥塞控制: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)
核心思想:客户端在发送操作的同时,立即在本地模拟操作结果并渲染,不等服务器确认。
例如玩家按“向前走“:
- 客户端立即在本地移动角色(预测)
- 同时发送操作给服务器
- 服务器计算后返回确认状态
- 客户端对比预测和确认——如果一致,无缝继续;如果不一致,纠正并重新预测
这是 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) │
│ │
├── 本地预测 │
├── 收到快照后纠正 │
└── 插值渲染 │
注意延迟的来源和补偿手段如何配合:
- 网络延迟 → 客户端预测来掩盖
- 状态同步频率低 → 插值来平滑
- 对方移动不可预测 → 服务器回溯来保证判定公平
小结
- 传输协议:强实时游戏用 UDP,不使用 TCP(避免 Head-of-Line Blocking 和不可控的拥塞控制)
- 同步模型:状态同步(服务器权威)vs 帧同步(确定性模拟),各有适用场景,现代游戏趋向混合方案
- 延迟掩盖三件套:客户端预测 + 服务器回溯 + 实体插值。三者协同工作
- 防作弊:服务器权威判定是基础,AOI 限制信息泄露是关键补充
下一节(2.4)将学习:持续在线世界型游戏问题模型,了解 MMORPG 的 AOI 和分片技术。
参考文献
-
Kjetil Raaen, “Response Time in Games: Requirements and Improvements”, Simula Research Laboratory, http://home.simula.no/~paalh/students/KjetilRaaen-phd.pdf ↩
-
Glenn Fiedler, “Game Networking” 系列文章, https://gafferongames.com/categories/game-networking/ ↩
-
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 ↩
-
Ruoyu Sun, “Game Networking Demystified, Part I: State vs. Input”, https://ruoyusun.com/2019/03/28/game-networking-1.html ↩
-
Tim Ford (Blizzard), “Overwatch Gameplay Architecture and Netcode”, GDC 2017, GDC Vault ↩
-
Glenn Fiedler, “What Every Programmer Needs To Know About Game Networking”, https://gafferongames.com/post/what_every_programmer_needs_to_know_about_game_networking/ ↩
-
Valve, “Lag Compensation”, https://developer.valvesoftware.com/wiki/Lag_Compensation ↩
-
Valve, “Source Multiplayer Networking”, https://developer.valvesoftware.com/wiki/Source_Multiplayer_Networking ↩