回滚同步
全库目录221
本文目录8
格斗输入晚到几帧,系统可以暂时预测,再回到历史状态重算。回滚同步需要可恢复的完整模拟状态、确定输入顺序和受控副作用。固定时间步只是条件之一,跨平台数值与容器顺序仍要验证。
三类同步思路
快照复制由服务端定期发送世界快照,客户端在已收到的快照间插值。实现直观,适合动作与射击,但带宽随实体和状态量增长。
锁步同步只同步每个 Tick 的输入,各端运行同一模拟。带宽较低,也方便回放,但要求确定性;浮点、容器遍历顺序、随机数和线程调度差异都可能让状态逐渐分叉。
确定性需要同时约束数值计算、输入和执行顺序。定点计算可以减少部分跨平台浮点差异;使用浮点时需锁定求值方式与编译选项,并做跨平台状态对比。随机数使用明确的种子和消费顺序,容器遍历保持稳定,输入带逻辑 Tick 序号。
模拟只消费该 Tick 已确定的数据,渲染时间和异步加载完成时刻由边界层处理。各端记录状态哈希,找到首次分叉的 Tick 后,再对比子系统和字段。
状态同步直接同步关键状态或状态差异,常和输入同步混合使用。实际项目不必追求一个标签覆盖所有系统:角色移动可预测,物理物体走快照,库存和任务走可靠事务。
断线、重连与回放
重连需要新的会话身份、完整或增量快照和安全的输入恢复边界。旧连接的延迟包不能影响新会话。玩家在断线期间由服务端托管、暂停还是移除,属于玩法规则,不该由传输层临时决定。
回放可以记录输入、权威事件或快照。只记输入体积小,但依赖版本和确定性;定期快照加事件更容易跳转和兼容。回放格式应写入构建版本、Tick Rate、随机种子和内容版本。
回滚流程
算法伪代码中snapshot[t]保存该Tick之前的完整状态,副作用以稳定事件ID由表现层提交。
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回调契约;代码入口供接入复核。