游戏卡顿白皮书 › 同步设计
指令同步的路径计算不一致 Command sync with divergent pathing
原因 ID sy-path-mismatch · 主责 研发团队·服务器开发 · 配合 研发团队·客户端开发
在含图示和实验的完整版中打开此卡片 →
只互传“去这里”,路径由双方各自计算时,计算稍有差异,角色或怪物就会走上另一条路,然后被拽回原位。
起因 点击移动、怪物追击时只发送目的地,路径由客户端另行计算 → 结果 地形数据差异、与其他角色碰撞、计算顺序不同,导致走了和服务器不同的路径 → 画面表现 怪物穿墙走着走着突然被挪走,点击移动的角色像打滑一样转向
- 症状
- 瞬移, 拉回
- 因素
- 延迟
- 谁会遇到
- 特定地点/分线, 只有我
- 何时出现
- 移动中/切换地图时
- 负责方
- 主责 研发团队·服务器开发 · 配合 研发团队·客户端开发
- 研发团队要做的事
- 服务器:把路径的中间点(路点)一并发送,定期对齐位置。客户端:偏差平滑收敛,使用与服务器相同的地形数据。
- 监控图上
- 偶发随机尖峰 · 各实体的位置校正次数、距离
- 查看位置
- 记录每个实体在服务器下发位置与客户端计算位置之间的差,把发生校正的坐标标到地图上。把双方的路径结果或位置汇总成校验和,定期对比,就能找出开始出现偏差的时间点
- 确认依据
- 校正集中在特定地形(门槛、狭窄通道、斜坡)或拥挤处,网络指标正常的玩家也在同一位置反复出现
- 排除依据
- 与地点无关、只在丢包或抖动冲高的瞬间校正,是线路问题。同一只怪物在多个人的画面上一起跳动,看是不是“怪物控制权在慢的客户端上”
- 确认手段
- 需要游戏服务器/客户端的日志和指标
- 深入了解
- 点击移动、Tab 锁定的游戏对 ping 不敏感,原因之一就是这种方式。代价是无法保证双方结果一致,所以一定要有定期对齐位置的机制。浮点运算的结果可能因 CPU 种类、编译器及其优化设置(包括 Debug 与 Release 版本的差异)而略有不同。在帧同步、回滚这类只互传输入、假定双方计算结果完全相同的结构中,这些微小差异会累积,可能导致两边画面的游戏状态分叉(desync)。
出处
- Deterministic Lockstep Gaffer On Games
即使在同一台机器上是确定的,编译器、OS、CPU 不同时,浮点结果也可能不同 - State Synchronization Gaffer On Games
把状态和输入一起发送,即使没有完美的确定性,也能让双方保持一致 - Peeking into VALORANT's Netcode Riot Games
丢包或两个角色要走到同一位置时,服务器与客户端的模拟会出现偏差,需要校正 - 1500 Archers on a 28.8: Network Programming in Age of Empires and Beyond Game Developer
极小的差异随时间放大,村民的路径一点点偏开。把世界、实体、寻路用校验和对比,找出不同步(out-of-sync) - Floating Point Determinism Gaffer On Games
同一段浮点代码,结果也可能因编译器、CPU 架构、Debug/Release 版本而不同。有过 AMD 和 Intel CPU 在超越函数上给出略有不同的值的案例 - /fp (Specify floating-point behavior) Microsoft
/fp:fast 会调整或合并浮点运算顺序,结果可能与其他 /fp 设置不同;用 FMA 合并的运算,结果也可能与分开乘再加不同
相关原因
同一层:同步设计
其他层中同样导致“瞬移”的原因
查看含图示和实验的原卡片