PVP 联机对战同步技术系列科普之《预测回滚帧同步》

理解预测回滚帧同步

日期:2026-11-09

理解什么是帧

假设你发出一记波动拳,气功波向前飞行,一秒钟后到达对手的位置。如果把这一秒拆成六十个小格,每经过一格,游戏就计算一次变化,让气功波向前移动一小段。走过六十格,气功波正好到达对手面前。这里的每一格,就对应一帧游戏演算。

你可能听过手机屏幕的刷新率是 60Hz,也就是每秒刷新六十次。不过,屏幕刷新率和游戏演算频率是两件事,并不是所有使用 60Hz 屏幕的游戏,都一定每秒演算六十帧。在这个例子里,我们也让游戏每秒演算六十帧,方便理解。

现在,把这场比赛搬到两部手机上。你是玩家 A,控制红方;对手是玩家 B,控制蓝方。双方进入同一个房间并开始游戏后,每部手机都要演算完整的对局:既要计算自己的角色,也要计算对手的角色和场上的气功波。可以把它们想象成两条分别向前推进的游戏时间线。

假设双方进度一致、所需输入也已经到达的情况。第 60 帧,红方发出波动拳;第 120 帧,气功波到达蓝方的位置。中间经过六十个帧间隔,也就是一秒钟。两部手机在同一帧算出相同的气功波位置,对命中或格挡的判断也一致。

波动拳的游戏时间轴
波动拳游戏时间轴

这条轴表示游戏内的演算进度;第 60 帧到第 120 帧之间,共经过 60 个帧间隔。

但实际联机时,操作消息需要时间才能传到另一部手机,两边的游戏进度也可能暂时不同。例如,开局消息到达有先后,或者某部手机短暂卡顿,就可能让 B 暂时落后 A 两帧。为了把过程讲清楚,接下来先假设双方以相同速度继续推进,这两帧的差距暂时保持不变。

这里再加入一个设定:预测延迟为 2 帧。本文用这个词表示输入从按下到参与游戏演算之间预留的帧数,也就是输入延迟。玩家在第 N 帧按下操作,游戏将它安排到第 N + 2 帧执行。这个等待可以为消息传输留出时间,但不保证远端总能及时收到输入。前面所说的“第 60 帧发出波动拳”指执行帧;沿用这一设定,发招按键应在第 58 帧采集。

当 A 来到第 120 帧时,气功波已经到达蓝方的位置。同一个现实瞬间,B 才来到第 118 帧,并在这一帧按下格挡,然后保持住。**按下不等于立即生效:118 + 2 = 120,所以格挡到 B 的第 120 帧才参与计算。**B 在按下时就发送输入,消息表达的是“第 120 帧执行格挡”,不必等格挡生效后再发送。本例还假设第 120 帧先应用格挡输入,再判断碰撞,格挡没有额外的启动时间,并能完全免除这次攻击的伤害。

容易混淆的量 本例设定 含义
预测延迟(输入延迟) 2 帧 B 在第 118 帧按下,第 120 帧执行
双方游戏进度差 A 领先 B 2 帧 同一现实瞬间,A120 对应 B118
消息传输时间 2 个帧间隔,约 33 毫秒 从 B 按下并发送,到 A 收到消息

这三个量在本例中恰好都与“2 帧”有关,但含义不同,也不要求始终相等。

问题在于,B 的格挡消息还在传输途中,A 此时并不知道对手已安排在第 120 帧执行格挡。如果 A 每次都等对方的真实输入到齐后再往前计算,网络等待就可能影响操作的响应。预测回滚的做法,是先根据已有信息补上暂时缺失的输入,继续推进游戏。

例如,A 上一次知道的蓝方输入是“没有格挡”,于是暂时假设蓝方仍然没有格挡,并用这个预测继续计算。因此,在 A 的第 120 帧里,气功波击中了蓝方,画面显示受击,血量也暂时扣除。这就是“预测”:真实输入还没到,先用一个暂定输入往前计算。它不是预先知道对手会做什么,也不代表当前显示的结果已经最终确定。

再经过两个帧间隔,B 来到第 120 帧。这一帧先执行之前安排好的格挡输入,再判断碰撞,因此 B 算出的结果是格挡成功,蓝方没有受到伤害。与此同时,A 已经走到第 122 帧,这时才收到消息:“B 在第 118 帧按下,格挡应在第 120 帧执行。”

这里要区分游戏帧号和消息的传输时间。A 收到消息时是第 122 帧,B 发出消息时是第 118 帧,但不能直接用 122 减去 118,就说消息在网络上传输了四帧的时间。两部手机原本就有两帧的进度差;按这个例子的设定,消息实际经过了两个帧间隔才到达。

沿现实时间对照两部手机的进度

预测回滚时间轴-01

预测回滚时间轴-02

两张图按现实时间先后排列。横轴是游戏帧号,圆点表示各端进度;消息从第一张图中的 B 发出,在第二张图中到达 A。

现实时间向下推进 A 的游戏进度 B 的游戏进度 格挡消息
起始瞬间 第 120 帧:预测蓝方未格挡,显示命中 第 118 帧:按下格挡,尚未生效 B 发出“第 120 帧执行格挡”
经过 1 个帧间隔 第 121 帧:沿用预测结果 第 119 帧:继续按住,等待生效 仍在传输途中
经过 2 个帧间隔 第 122 帧:收到真实输入,发现预测有误 第 120 帧:格挡输入生效,挡住攻击 消息到达 A

表格的每一行对应同一个现实瞬间。横向看,A 始终暂时领先 B 两帧;纵向看,消息经过两个帧间隔到达。在本例的 60 帧/秒设定下,这段时间约为 33 毫秒。

收到真实输入后,A 发现自己在第 120 帧使用的预测不对。这个错误已经影响了后面的碰撞和血量,所以仅仅从第 122 帧开始让蓝方格挡,还不能纠正之前的结果。A 需要恢复到第 120 帧开始前保存的游戏状态,把相应的预测输入替换成收到的真实格挡输入,再沿用其他输入记录,按顺序重新计算到第 122 帧。回滚起点由预测出错的输入生效帧决定,而不是由按键采集帧决定;这里不需要因为按键发生在第 118 帧,就一定退回第 118 帧。如果可用的保存点更早,也可以从更早的状态开始重演。

预测回滚时间轴-03

这一次,第 120 帧的碰撞发生时,蓝方已经处于格挡状态。原先的“命中”变成了“格挡成功”,临时扣除的血量恢复,A 的最新画面也随之修正。先预测缺失的输入,发现预测有误后恢复历史状态,再带着正确输入重新演算,这就是预测回滚帧同步,也叫 Rollback Netcode。

预测回滚时间轴-04

第 3 张图的圆点位于第 120 帧刻度,表示这一帧的起点,尚未执行第 120 帧的输入和碰撞计算。后两张图展示 A 的内部处理过程,B 的第 120 帧仅作为结果对照,不表示 B 必须停下来等待。A 恢复的是第 120 帧开始前的状态,再逐帧重演到自己的当前帧;玩家画面不需要倒放。

真正触发这次回滚的,是已经参与演算的预测输入与后来收到的真实输入不一致。输入迟到本身,并不一定需要回滚。如果 A 预测蓝方没有格挡,收到的真实输入也确实没有格挡,那么这部分预测就不需要纠正。两边暂时存在进度差,也不等于一定发生回滚。

A 收到迟到输入后的处理流程

图中的回滚路径表示游戏内部的计算过程。A 重演后仍回到自己的第 122 帧,不会停留在历史帧,也不需要让画面倒着播放。

听到“回滚”,你可能会以为游戏画面要倒着播放:气功波先飞回来,角色退回原位,再把攻击过程重新演一遍。实际处理通常是在后台快速恢复状态并重新计算,画面直接呈现修正后的结果,不必逐帧播放这段倒退和重演过程。

但快速重算不代表玩家完全看不到变化。刚才显示命中,随后变成格挡,仍然可能被察觉;角色的位置或动作也可能出现修正。延迟越大、需要预测的跨度越长,或者预测频繁出错,体验就越容易受到影响。预测回滚让游戏能够在输入尚未到齐时继续响应,但不会让网络延迟消失,也不保证永远无需等待。

另一个容易混淆的问题是:A 回滚之后,两部手机的进度是不是就对齐了?并不是。A 恢复历史状态后,重新计算回自己的第 122 帧,纠正的是之前的预测错误。双方现在对第 120 帧那次碰撞的判断一致了,但在同一个现实瞬间,仍然可能处于不同的游戏帧。

要缩小这种进度差,游戏还可以持续比较双方的进度,必要时让落后的一方加快计算,或让领先的一方稍等一下。加快计算仍然需要按顺序执行中间的帧,并不是直接跳过这些帧。这样的进度校准是逐步进行的,不是每收到一条操作消息就立刻对齐;持续卡顿或网络异常,也不能仅靠校准解决。回滚重演负责纠正预测错误,进度校准负责缩小当前进度差,两者可以配合,但作用不同。

预测回滚也并非只能用于双人对战。不过,人数增加以后,每个客户端可能需要预测更多玩家的输入。一位玩家的输入迟到,并且与其他客户端已经使用的预测不同,就可能让多个客户端分别回滚,带来更多修正和重复计算。是否发生回滚,仍取决于各个客户端实际使用过的预测,不是某个玩家的消息一迟到,所有人就必然一起回滚。

因此,多人游戏可以使用预测回滚,但需要结合玩法、消息传递方式、允许预测的范围,以及设备能够承担的重演开销来评估,不能直接照搬双人方案。帧广播同步和状态广播同步也是可以比较的选择,各有取舍,并不意味着换一种方案就能消除延迟或卡顿。

理解预测回滚的关键,是记住游戏可以先用暂定输入继续运行,再根据真实输入纠正结果。它让当前的操作响应不必总是等待远端消息,同时也要求游戏能够保存状态、重演过去,并承受预测错误带来的修正。

末尾打个广告

本人开发的 《PVP Sync 联机对战引擎》已上架商城,路过请留个赞,谢谢!后续连载会讲解一些联机游戏的开发技巧和SDK的设计思想

4赞

先占位后观看:+1: