怎么让两个玩家在同一时间看到同一个世界?
单机游戏是个封闭系统:玩家按键,引擎响应,状态为真,因为只有一份。加上另一台设备上的第二个玩家,这个保证就蒸发了。现在有两份状态,中间一根各 80ms 延迟的线,还有一个玩家会在"自己错了"的瞬间察觉。实时多人不是个你能外挂的功能;它是对"真"这个概念的重设计。下面是团队低估的部分。
Q:为什么小游戏里的同步比单机难一个量级?
因为"真"变成了谈判。单机里引擎是法官;多人里,法官是网络,而网络又慢、又丢包、有时还撒谎。现在每个操作都有个往返:你的输入离开设备、到达对面、被调和、再作为状态回来——而在这段往返里,对面那个玩家已经动了。小游戏的约束让这更糟:你是在手机蜂窝网上做这件事,不是有线 PC,所以你的延迟预算更紧、掉线率更高。多数团队把"以后再加大多人"写进预算,后来发现那个"以后"是重写,不是追加。
Q:权威、lockstep、预测——到底怎么选?
三种架构,三种诚实的权衡。服务器权威意味着一台机器持有真值、客户端是哑终端;它是唯一能挡作弊的模型,但给一切都加了一次往返,不配预测就会很卡。Lockstep 让每个客户端跑同一份确定性模拟、只交换输入;带宽便宜,但一个慢 peer 就卡住整局,任何非确定性都会让所有人 desync。客户端预测 + 服务器调和让本地玩家感觉即时、同时服务器悄悄纠正他——FPS 和竞速的标准做法,也是最多代码要写对的地方。对休闲小游戏来说,真正的问题是:你到底需不需要实时?回合制或异步能消除这里 90% 的痛苦。
Q:插值、回滚、补偿——延迟到底是怎么被"藏"起来的?
你不是消除延迟,你是令人信服地骗过去。插值把其他玩家渲染在几帧之前,让他们的运动平滑,而不是在网络更新之间瞬移——代价是每个人看起来都稍微延迟,玩家能接受。回滚(格斗游戏用)则假设对面输入已经到了、向前模拟,如果没到就回退重放——感觉即时,但要求完全确定性、可快照的状态。像 lag shielding 这种网络补偿会伪造一个掉线玩家最后的动作,让他不冻结。艺术在于选你这个品类能活下来的那个谎言:平滑而稍迟,还是即时而回滚。
Q:怎么判断自己的游戏该不该做实时?
先做诚实测试。如果你的游戏是解谜、卡牌对战、或者任何 200ms 延迟不改变结果的类型,你几乎肯定想要异步或回合制,把预算花在匹配上而不是网络代码上。实时只在"同时性本身就是乐趣"时才值回票价——竞速、射击、协作闪避。而共享 runtime 在这里比团队预期更有用:跨所有小游戏一套一致的联网层,意味着那段最难写的同步代码你只写一次,而不是每个产品写一遍。下面这张表是多数团队跳过的门槛。
| 如果你的品类是…… | 同步模型 | 为什么 | 它要你付出什么 |
|---|---|---|---|
| 解谜 / 卡牌 / 回合 | 异步或回合制 | 延迟不改变结果 | 几乎没有网络代码工作 |
| 竞速 / 射击 / 协作 | 客户端预测 + 服务器权威 | 同时性就是乐趣 | 预测 + 调和代码 |
| 确定性策略 | Lockstep | 带宽便宜、公平 | 一个卡顿 peer 拖垮全部 |
| 休闲、不确定 | 先异步、再量 | 实时可能是个坑 | 猜错了要返工 |
实时多人是对每一帧的征税。只在"乐趣在于同时性"的地方才收它。