网络同步是 Unity 手游里最「看起来简单、做起来要命」的一环。本文系统梳理两大核心范式------帧同步(Lockstep)与状态同步(State Sync),从原理、确定性、权威归属、带宽、延迟补偿、断线重连、反作弊,到 Unity 落地要点,多方位拆解。最后给一份选型决策表,并附一个真实上线项目的取舍案例。
先厘清两层概念
聊同步前,先分清两个经常被混为一谈的层次:
| 层次 | 回答的问题 | 典型选项 |
|---|---|---|
| 同步范式 | 网络上「传什么」、对端「怎么用」 | 帧同步 / 状态同步 |
| 延迟补偿 | 怎么掩盖网络延迟 | 客户端预测 / 插值 / 回滚(Rollback) |
回滚不是帧同步/状态同步之外的第三种并列范式,而是叠在它们之上的一层延迟补偿技术。 这是最常见的认知误区,后面会单独澄清。
判定一个项目属于哪种范式,唯一标准是:看对端收到数据后如何使用它------是「喂进本地确定性逻辑重算」,还是「直接套用收到的结果」。

一、帧同步(Lockstep)
1.1 核心原理:同步输入,各自重算
帧同步的「帧」,指的是逻辑帧(Logic Tick),不是渲染帧。
客户端 A 服务器 / Host 客户端 B
│ 上报输入(按键/摇杆) ──────────▶ │
│ 收集所有玩家输入 │
│ ◀──────────── 广播第 N 帧所有玩家输入 ──────────────────────▶
│ 用确定性逻辑重算第 N 帧结果 │
- 玩家只上报操作输入(第 N 帧按了什么、摇杆方向),不上报位置、伤害这些结果。
- 服务器(或 Host 主机)不跑游戏逻辑,只把一段时间内所有玩家的输入打包广播。
- 每个客户端拿到输入后,用完全相同的确定性逻辑,各自重算出这一帧的游戏状态。
- 因为所有客户端初始状态相同、输入序列相同、逻辑相同,所以逐帧算出的结果天然一致,无需互相传状态。
1.2 生死线:确定性(Determinism)
帧同步能成立的前提是确定性模拟 :同样的初始状态 + 同样的输入序列 → 必须算出逐位相同的结果。一旦某台机器算出一丁点偏差,后续所有帧都会累积放大,最终「双方看到的是两场不同的游戏」。
破坏确定性的四大元凶:
| 元凶 | 为什么坏 | 应对 |
|---|---|---|
| 浮点数 | 不同 CPU/编译器浮点行为不同,微小误差大量计算后放大 | 用**定点数(Fix64)**替代 float |
| 随机数 | 每台机器 rand() 序列不同 |
用共享种子的可重放随机流 |
| 系统时间 | 挂钟时间各端不一致 | 逻辑只用逻辑帧计数,不读墙钟 |
| 非确定性物理/库 | 物理引擎、字典遍历序等可能不确定 | 慎用甚至禁用,替换为确定性实现 |
浮点问题最直观:
0.1 + 0.2 != 0.3。在帧同步里,一个float累积误差跑十几分钟就能让一个单位的位置差出好几格。所以成熟帧同步引擎几乎一律上定点数。
1.3 逻辑帧驱动:固定 tick + 等输入到齐
- 所有客户端以相同的固定 tick rate 推进(如 15/30/60 逻辑帧每秒)。
- 每推进一帧,必须等这一帧所有玩家的输入都到齐 。任何一个玩家延迟,所有人都要等------这就是帧同步最痛的「木桶效应」:游戏节奏被最慢的玩家拖累。
- 缓解手段:乐观帧锁定(先预测推进,错再回滚)、延迟缓冲(故意加少量延迟吸收抖动,本质已向回滚靠拢)。
1.4 优劣与典型场景
优点:
- 带宽极低:只传输入,同屏几百个实体也不怕(这是 RTS 选它的根本原因)。
- 天然回放/观战:存输入序列即可完整回放,录像文件极小。
- 服务器压力小:只转发输入,不做模拟。
缺点:
- 确定性改造成本极高:定点数、固定 tick、禁随机,物理与浮点相关代码都要重写。
- 断线重连难:错过中间输入就无法继续,需从头重放全部帧。
- 作弊防护弱:每个客户端都掌握完整游戏状态,地图全开(Maphack 天然可行)。
- 同步调试难:出现一帧不一致要逐帧 diff,定位极其痛苦。
典型场景:RTS(星际争霸、帝国时代)、MOBA(王者荣耀采用帧同步)、回合制策略。
1.5 Unity 落地要点
- 逻辑帧 vs 渲染帧分离 :逻辑跑在
FixedUpdate(或自定义 tick 循环),渲染做插值平滑表现。 - 确定性输入驱动 :用确定性随机(自定义 LCG 等)替代
UnityEngine.Random。 - 定点数:引入 Fix64 库,或用整数定点(如「毫米」做单位)。
- 禁用非确定性 API :
Time.time、float运算、Dictionary无序遍历(需排序后遍历)都要封禁或替换。 - 帧率无关:所有移动/物理按逻辑帧 delta 推进,不依赖渲染帧率。
二、状态同步(State Sync)
2.1 核心原理:同步结果,直接套用
状态同步与帧同步正好相反------同步「结果」而非「输入」。
客户端 A (权威) 服务器 客户端 B
│ 上报输入/本地算好状态 ──────────▶ │
│ 服务器裁决/转发状态 │
│ ◀────────────────── 下发最新状态(位置/HP/伤害) ────────────▶
│ 对端直接套用结果(或插值) │
- 权威端广播状态结果:位置、HP、伤害值、buff 状态......
- 对端拿到结果后直接套用 ,或朝目标点插值 平滑过渡,不重算逻辑。
- 权威在谁手里,谁决定「真值」;对端只是「表现结果」。
2.2 权威归属:服务器权威 vs 客户端权威
状态同步的核心议题是「谁是权威」。两种主流取法:
| 服务器权威(Server Authority) | 客户端权威(Client Authority / 分布式权威) | |
|---|---|---|
| 逻辑在哪算 | 服务器 | 客户端(各自/指定主机) |
| 延迟 | 状态变化约 1 RTT | 约 ½ RTT,更低 |
| 服务器开销 | 重(跑全量模拟) | 轻(只转发/路由) |
| 反作弊 | 强(服务器校验一切) | 弱(信任客户端) |
| 典型场景 | 竞技 PVP / FPS / 精确物理 | 社交 / 休闲 / Co-op |
- 服务器权威 :Unity Netcode for GameObjects 的默认拓扑。客户端发请求(
ServerRpc),服务器裁决后写NetworkVariable下发。NetworkTransform默认服务器权威,NetworkRigidbody物理只在服务器跑。 - 客户端权威 / 分布式权威 :Unity 6 + Netcode v2.2+ 引入的「Distributed Authority」拓扑,每个客户端当自己的 mini-host,可 spawn 自己的对象、
NetworkVariable默认 owner 写 / 所有人读。牺牲安全性换低延迟、低成本。
两者不是非黑即白------现实里常是**「角色层客户端权威 + 关键经济/胜负服务器权威」的混合**。
2.3 延迟补偿:状态同步的「手感」来源
状态同步的权威往返有天然延迟,不补偿就会「按键后人物愣一下才动」。三层补偿手段:
- 插值(Interpolation):渲染端故意滞后 1~2 个 tick,在已知的旧状态与旧状态之间平滑过渡,消除网络抖动带来的「瞬移」。代价是永远看到的是「过去 100ms 的世界」。
- 客户端预测(Client Prediction) :本地输入立即响应,不等服务器回包;服务器回包后做校正(Reconciliation),若本地预测与服务器权威不符,就回滚到服务器状态重放本地输入。
- 回滚(Rollback):见下一节。
2.4 优劣与典型场景
优点:
- 不要求确定性:各端独立模拟,以权威结果为准,客户端差异会被校正。
- 断线重连容易:拉一份最新状态快照即可继续。
- 作弊防护强(服务器权威时):服务器校验一切,客户端改不了真值。
缺点:
- 带宽较高:传实体状态,需压缩/差分/interest management 优化。
- 服务器成本高(服务器权威时):服务器要跑全量模拟。
- 实现复杂:预测/校正/插值/回滚一环套一环,调起来费劲。
典型场景:FPS(CS:GO/Valorant)、MMO(魔兽世界)、LOL/DOTA2、格斗。
2.5 Unity 落地要点
- Netcode for GameObjects + Unity Transport :官方栈,
NetworkVariable(状态)、NetworkTransform(位置)、ServerRpc/ClientRpc(消息)。 - 传输层 :
UnityTransport底层是 ENet/UDP;WebGL 走 WebSocket。 - 权威设置 :
NetworkManager > Network Topology选服务器权威或分布式权威;用IsServer/HasAuthority做对象级判断。 - 带宽优化 :
NetworkTransform开插值、限同步频率;大状态用自定义序列化;Interest Management只同步视野内实体。
三、回滚网络(Rollback):澄清它的位置
回滚不是第三种范式,而是「延迟补偿」的一个高级手段,可叠在状态同步或锁步上。核心是「不等待,先预测,错了再回滚」:
- 预测(Predict):对手输入没到时,先预测(通常「沿用上一帧输入」)。
- 立即模拟(Simulate):本地输入 + 对手预测输入,立即推进并渲染,本地操作零延迟。
- 比对(Compare):对手真实输入到达后与预测比对。
- 回滚重模拟(Rollback & Resimulate):若预测错,回到分歧帧的存档,用正确输入重新模拟到当前帧,一帧内完成,肉眼表现为短暂「跳变」而非卡顿。
硬性前提还是确定性模拟 ------必须能随时保存/载入状态、不渲染地执行一帧。GGPO 官方文档的名言:「难点是确定性本身,而不是 rollback 机制」。
回滚是 1v1 格斗的「黄金标准」(街霸 6、GGPO 系),它让离线练出的反应速度能直接搬到线上。但它对确定性要求极高、状态序列化与回滚架构复杂,不适合实体多、非确定性的场景。
四、双范式全景对比
| 维度 | 帧同步(Lockstep) | 状态同步(State Sync) |
|---|---|---|
| 同步内容 | 输入指令 | 状态结果 |
| 对端如何用 | 喂确定性逻辑重算 | 直接套用 / 插值 |
| 逻辑在哪算 | 各客户端各自算 | 权威端算 |
| 确定性要求 | 极高(定点数/固定tick/禁随机) | 无(结果为准) |
| 带宽 | 极低 | 较高(需优化) |
| 断线重连 | 难(从头重放) | 易(拉快照) |
| 反作弊 | 弱(客户端有全量状态) | 强(服务器权威可校验) |
| 回放/观战 | 轻量(存输入即可) | 需额外快照/回放系统 |
| 实现复杂度 | 中(确定性+同步调试难) | 高(预测/校正/插值复杂) |
| 典型场景 | RTS / MOBA | FPS / MMO / 格斗 |
要点 :两者的本质分歧不是「用不用 UDP」或「用不用服务器」,而是同步输入还是同步结果。带宽、确定性、反作弊、断线重连这些差异,都是这个分歧的推论。
五、实战案例:一个 Unity 手游的取舍
本节给一个真实上线项目(Unity 手游项目,中轻度对抗)的取舍,作为「选型落到代码」的参照。细节从简,重在决策逻辑。
项目最终选的是:客户端权威状态同步。
为什么是状态同步而非帧同步? 同屏实体少(不需要帧同步的带宽优势),对抗强度中等(不必上服务器权威的强校验),状态同步不需要确定性改造、断线重连也简单。判定依据看对端用法------位置命令「直接赋值并插值」:
csharp
public class xxxSyncMCommand : PooledCommand<xxxSyncMCommand>
{
public Vector3 Position { get; private set; } // 传的是位置结果,非输入
public override void Execute(CommandTypes commandTypes)
{
// 对端收到后:把位置作为目标点交给控制器插值,不重算轨迹
MessageSystem.Instance.SendSync(Character.FieldObjectController as IEventListener,
SetTargetEvent.CreateSyncTarget(Position, Direction, AnalogueMode));
if (Character.FieldObjectController is NetworkCharacterController nc)
{
nc.ReplicationPosition = Position; // 直接覆盖复制位置
nc.ReplicationDirection = Direction;
}
}
}
权威怎么放? 分布式客户端权威,双层模型:

- 角色层 :每个玩家对自己的角色权威,谁的角色谁算。
Player.Local天然归属自己,只有本地玩家发布的命令才广播,且本地立即执行:
csharp
public static void Publish(Player owner, Command command) {
if (owner == Local) { // 只有本地玩家发布的命令才广播
if (ShouldWriteCommand(command))
xxxcommandPipeline?.SendCommand(command);
command.Execute(CommandTypes.None); // 本地立即执行
}
}
- 公共实体层 :怪物/NPC 归 SuperClient(第一个存活玩家),掉线时服务端推
reassign-owner迁移。
传输怎么走? 关键在「位置可丢、伤害不可丢」的矛盾,用双 QoS 通道解决:
一句话总结这个案例:状态同步选范式、客户端权威省成本------是「中轻度对抗 + 同屏实体少」场景下很典型的一种落法。
六、选型决策:没有银弹

选同步方案,先问三个问题:
- 局内同屏实体多不多? RTS/MOBA 同屏几十上百实体 → 帧同步(只传输入才扛得住带宽);FPS/MMO 实体少 → 状态同步更简单。
- 是否要求强一致防作弊? 竞技 PVP → 服务器权威状态同步;休闲 Co-op → 客户端权威可接受,省成本降延迟。
- 能否承受确定性改造成本? 帧同步/回滚要定点数 + 固定 tick + 禁随机,成本极高;状态同步无需确定性。
实战高频出现的是混合方案 :核心战斗帧同步 + 经济/匹配状态同步,断线重连用「帧同步追帧 + 状态快照」加速(王者荣耀/LOL 手游同款)。把范式当光谱而不是开关,按子系统选,比纠结「全局用哪种」更实用。