
多人在线游戏最难的事情之一是让所有玩家看到“同一个世界”。网络存在延迟、抖动、丢包和断线。假如四个玩家同时操作服务端和每个客户端收到这些操作的时间都不同如果没有同步机制甲看到的牌已经打出乙的画面里却还没摸牌最终每个人都会进入不同的游戏状态。解决这个问题的主流方案有两类状态同步与帧同步。一、状态同步服务端告诉你“现在世界是什么样”状态同步的核心思想是服务端维护唯一正确的游戏状态并把状态变化或状态快照同步给客户端。客户端更多是负责展示以及在有限范围内做本地交互预测。玩家操作 → 发送给服务端 → 服务端校验并执行规则 → 服务端广播状态变化 → 各客户端更新画面以麻将为例服务端是唯一可信裁判。玩家点击出牌后客户端把“我想打这张牌”发送出去服务端检查是否轮到该玩家、这张牌是否存在、是否受立直或振听限制通过后服务端更新牌局并广播“某玩家打出了某张牌”。客户端收到后才正式把手牌移入河牌、更新剩余时间、显示相关特效。状态同步的常见形式1. 全量快照服务端定期发送完整世界状态例如第几局、谁是庄家、各家分数 所有公开牌、副露、宝牌、剩余牌数 当前行动者、倒计时、可执行操作优点是简单可靠特别适合断线重连客户端拿到快照后可以直接恢复。缺点是数据量大。如果高频同步角色位置、子弹、物理对象全量快照会造成明显带宽压力。2. 增量状态服务端只发送变化的部分例如玩家 A 摸牌 玩家 B 打牌 玩家 C 立直 宝牌翻开 当前行动者切换优点是带宽更小表现更及时。缺点是客户端必须严格按顺序处理事件如果中间丢失一条消息状态可能逐渐偏离通常需要定期快照校正。3. 快照加增量事件这是大多数在线游戏较实用的方案初始快照 连续增量事件 定期校验快照 断线后重新拉取快照麻将、卡牌、回合制战棋、RPG 战斗等规则明确且服务端权威的游戏通常很适合这种模式。二、帧同步服务端告诉你“每一帧大家输入了什么”帧同步的核心思想是服务端不直接同步世界结果而是收集所有玩家输入并让所有客户端在相同帧序下执行同一份逻辑。玩家输入 → 上传服务端 → 服务端按帧收集输入 → 广播“第 N 帧所有玩家输入” → 所有客户端执行第 N 帧逻辑例如一款实时对战游戏中第 120 帧收到玩家 A向右移动 玩家 B释放技能 2 玩家 C停止移动 玩家 D无操作所有客户端都在自己的第 120 帧执行完全相同的规则。只要初始状态相同、输入顺序相同、逻辑计算完全确定最终世界状态就会一致。服务端更像“输入排序器”和“裁判”而不一定需要每帧计算整个游戏世界。帧同步的关键前提确定性帧同步要求各客户端执行后得到同样结果因此游戏逻辑必须足够确定。以下内容必须尽量避免或统一浮点数计算差异不同平台的随机数实现物理引擎结果不一致依赖本地时间遍历无序容器异步回调触发顺序不同不稳定的对象创建和销毁顺序。常见处理方式包括使用整数、定点数代替关键浮点计算使用固定随机种子固定逻辑帧率例如每秒 20、30 或 60 帧保证对象遍历顺序固定让随机、寻路、碰撞、伤害等逻辑完全由统一规则决定。如果确定性被破坏一开始可能只差一个很小的位置误差几百帧后却可能演变为完全不同的战局。三、状态同步与帧同步的核心区别对比点状态同步帧同步服务端同步内容状态结果、状态变化或快照玩家输入与帧序谁计算游戏结果主要由服务端所有客户端同时计算服务端压力较高相对较低客户端要求较低很高需要确定性逻辑带宽消耗与对象数量、状态频率相关通常较低主要传输入断线恢复拉取快照即可需要快照加后续输入重放防作弊能力较强服务端权威较弱需要额外校验适用场景麻将、卡牌、回合制、MMO、射击RTS、MOBA、格斗、部分动作竞技一句话概括状态同步同步的是“结果”。帧同步同步的是“过程中的输入”。四、延迟问题为什么帧同步需要预测如果严格等待服务端下发每一帧输入游戏手感会很差。假设网络延迟为 100 毫秒逻辑帧率是每秒 30 帧。玩家按下移动键后如果必须等待服务器确认再执行至少要等 3 帧左右才能动起来操作会明显滞后。因此帧同步通常会引入本地预测。玩家按下移动 → 客户端立即预测执行 → 同时把输入发给服务端 → 服务端收集并广播权威输入帧 → 客户端收到后进行确认或修正玩家自己的操作先在本地生效画面立即响应之后再由服务端广播的权威输入确认。这就是预测。预测并不意味着客户端拥有最终裁决权。它只是为了改善手感。最终仍应以服务端确认的输入帧、规则校验或权威状态为准。五、什么是回滚预测带来一个问题客户端可能提前执行了一个后来被否定的操作。例如玩家本地预测第 100 帧释放技能。客户端立即播放动作、计算命中。服务端收到请求后发现该技能仍在冷却或者玩家在第 99 帧已经被控制。服务端下发的权威第 100 帧中没有这次技能输入。此时客户端已经“走错了未来”就需要回滚。回滚的基本流程保存历史状态 → 本地预测执行未来帧 → 收到较早的权威输入或权威状态 → 回到对应历史帧 → 应用权威数据 → 重新模拟后续各帧举例本地已经模拟到第 110 帧 服务端确认第 100 帧存在差异 回滚到第 99 帧 → 应用服务端确认的第 100 帧输入 → 重新计算第 100 到第 110 帧 → 得到修正后的当前状态回滚并不是把画面瞬间倒放。逻辑状态会回退并重新计算表现层通常会通过平滑修正来避免角色突然跳动。回滚需要保存什么为了能够回到过去客户端需要保留一个有限窗口内的历史数据每个逻辑帧的完整或可恢复状态每个逻辑帧收到的权威输入本地预测输入随机数状态必要的对象生命周期信息。例如保留最近 1 到 3 秒的帧历史。若逻辑帧率是每秒 30 帧则要缓存 30 到 90 帧的数据。窗口过小网络抖动时可能无法回滚到足够早的位置窗口过大内存和重算成本会增高。六、预测与回滚的典型组合实时竞技游戏中常见模式如下客户端 立即执行本地输入 保存每帧历史状态 上传输入 服务端 校验输入 组织权威帧 广播所有玩家输入或权威结果 客户端收到权威帧 若与预测一致继续运行 若不一致回滚并重新模拟其中有三种常见策略。1. 输入延迟所有人都延迟若干帧执行输入等大多数网络消息到齐后再模拟。优点是简单回滚少。缺点是操作有固定延迟网络差时体验明显下降。2. 预测加回滚客户端先执行后校正。优点是手感好适合格斗、动作、射击等强操作游戏。缺点是实现复杂需要严格确定性和历史状态管理。3. 混合方案常见于商业游戏对自己角色使用预测对其他玩家使用插值或有限预测对关键规则使用服务端确认对位置、动画等表现进行平滑修正对资源、伤害、胜负等结果保持服务端权威。七、帧同步中的随机数与确定性随机数是帧同步最容易踩坑的部分之一。如果每台设备随意调用本地随机数即使输入完全一致也可能在某一帧抽到不同结果随后整个战局都会分叉。正确做法通常是对局开始时确定随机种子 → 每个客户端使用同一种伪随机算法 → 在完全一致的调用顺序下取随机数 → 所有人得到同样结果但仅仅统一种子还不够。调用次数也必须一致。假如某个客户端因一个分支条件不同多调用了一次随机数之后所有随机结果都会错位。因此帧同步项目中应避免让表现层、异步逻辑或平台差异影响核心随机数调用。八、麻将更适合哪种同步方案麻将通常更适合状态同步而不是完整帧同步。原因是麻将是离散操作和回合推进不是高频移动规则校验强服务端必须防作弊存在隐藏信息不能把完整状态或随机过程交给所有客户端断线重连天然适合用服务端快照恢复玩家对几十毫秒级本地响应的要求远低于格斗或射击游戏。麻将中可以借鉴帧同步的思想例如为每条事件提供严格递增的顺序号客户端按顺序消费事件重连后从快照序号继续接收事件回放按同一事件序列重建状态对牌桌表现使用本地队列确保动画不因网络抖动乱序。但不建议把牌局规则完全交给客户端同时计算。尤其牌山、手牌和隐藏信息应始终由服务端权威维护。九、如何选择同步方案可以根据游戏特征判断。适合状态同步的情况回合制、卡牌、麻将、棋类规则复杂且强防作弊隐藏信息较多可接受服务端权威带来的少量操作延迟需要稳定的断线恢复和跨端一致性。适合帧同步的情况实时操作强单位或对象数量多输入数据远小于状态数据希望降低服务端模拟压力可以投入成本保证确定性可以接受预测、回滚和反作弊体系的复杂度。十、总结状态同步和帧同步没有绝对优劣核心差异在于“同步结果”还是“同步输入”。状态同步强调服务端权威、规则安全和恢复简单帧同步强调统一模拟、低带宽和实时手感。预测解决“等待服务端太慢”的问题先让客户端快速响应。回滚解决“预测可能出错”的问题收到权威结果后回到过去重新推演未来。对于实时竞技游戏预测与回滚往往是帧同步体验的关键对于麻将等强规则、隐藏信息、多断线恢复需求的游戏状态同步加快照、事件序列和严格版本控制通常是更稳妥的工程选择。