← ALL ARTICLES
游戏网络3 MIN READ

回滚同步

全库目录221
本文目录8

格斗输入晚到几帧,系统可以暂时预测,再回到历史状态重算。回滚同步需要可恢复的完整模拟状态、确定输入顺序和受控副作用。固定时间步只是条件之一,跨平台数值与容器顺序仍要验证。

三类同步思路

快照复制由服务端定期发送世界快照,客户端在已收到的快照间插值。实现直观,适合动作与射击,但带宽随实体和状态量增长。

锁步同步只同步每个 Tick 的输入,各端运行同一模拟。带宽较低,也方便回放,但要求确定性;浮点、容器遍历顺序、随机数和线程调度差异都可能让状态逐渐分叉。

确定性需要同时约束数值计算、输入和执行顺序。定点计算可以减少部分跨平台浮点差异;使用浮点时需锁定求值方式与编译选项,并做跨平台状态对比。随机数使用明确的种子和消费顺序,容器遍历保持稳定,输入带逻辑 Tick 序号。

模拟只消费该 Tick 已确定的数据,渲染时间和异步加载完成时刻由边界层处理。各端记录状态哈希,找到首次分叉的 Tick 后,再对比子系统和字段。

状态同步直接同步关键状态或状态差异,常和输入同步混合使用。实际项目不必追求一个标签覆盖所有系统:角色移动可预测,物理物体走快照,库存和任务走可靠事务。

断线、重连与回放

重连需要新的会话身份、完整或增量快照和安全的输入恢复边界。旧连接的延迟包不能影响新会话。玩家在断线期间由服务端托管、暂停还是移除,属于玩法规则,不该由传输层临时决定。

回放可以记录输入、权威事件或快照。只记输入体积小,但依赖版本和确定性;定期快照加事件更容易跳转和兼容。回放格式应写入构建版本、Tick Rate、随机种子和内容版本。

回滚流程

算法伪代码中snapshot[t]保存该Tick之前的完整状态,副作用以稳定事件ID由表现层提交。

text
if lateInputTick >= oldestSavedTick:
    state = Restore(snapshot[lateInputTick])
    for tick in [lateInputTick, nextUnsimulatedTick):
        snapshot[tick] = Save(state)
        state = Simulate(state, confirmedOrPredictedInputs[tick])
    CommitDeduplicatedPresentationEvents()
else: use explicit resync policy

快照边界与副作用

令 snapshot[t] 表示执行第t步输入之前的状态。预测输入为 [+1,+1,+1] 时,步前状态是 [0,1,2],当前结果为3。第1步真实输入迟到且为-1,恢复 snapshot[1]=1,执行-1得到0,再执行第2步的+1,当前结果变成1。若错误恢复到第1步之后的快照,真实输入会叠加到已经消费预测输入的状态上。

重算范围采用半开区间 [lateTick,nextTick),nextTick 是下一个尚未执行的步。快照覆盖位置、速度、能力计时器、随机数状态、对象ID分配器和会影响后续求解的持久状态。只复制渲染变换无法恢复下一步模拟。

表现事件以 (实体ID,动作实例ID,Tick,事件槽) 标识。重模拟后,把窗口中的事件集合与上一版本比较:相同ID不重复播放,新事件补发,可撤销的旧预测事件撤销或淡出。只做去重还不够,因为预测过的爆炸可能在真实输入下根本不会发生。库存等不可撤销事务由确认状态提交。

每步保存S字节、窗口W步,快照存储约为S×W;一次迟到最坏需要重算W步。分别记录保存耗时、重算峰值和表现修正,才能判断扩大窗口的成本。

验证方法

对固定输入逐Tick比较状态hash,找首次分歧;迟到窗口边界、暂停、重连与副作用去重分别测试。快照与锁步属于同步选择背景,完整快照插值见快照同步。

实现与证据

2026-10-22,以本机 Python 3.11 运行 python 知识库/examples/revision_16_21/test_reference.py,17项检查通过。参考实现与测试输入可复现本页注明的机制。 本页的确定性整数模型检查步前恢复和事件序列重建;跨平台浮点、完整物理状态和音频撤销未运行。

相关主题

参考资料

  • GGPO SDK:README与save_game_state、load_game_state、advance_frame回调契约;代码入口供接入复核。