上一篇讲到,《苍穹对决》用 WebRTC 让玩家浏览器两两直连,连信令服务器都省了。但连接建立只解决了"怎么连上",一个更尖锐的问题立刻浮现:没有服务器,谁说了算?两发子弹同时命中,谁死谁活听谁的?一个玩家说自己没死,另一个说自己打死了,裁判在哪?这篇就讲《苍穹对决》给出的答案:听房主的。
一、"谁说了算":没有裁判的球场
网络对战里有一个铁律:状态必须有一个权威来源。如果每台设备都自己判断"我打中了他",两台设备的判定结果几乎必然不同——网络延迟让它们看到的世界本来就是两个略有差异的版本。传统网游里,这个裁判是服务器;没有服务器的游戏,必须自己造一个裁判出来。
《苍穹对决》把裁判角色交给了房主——创建房间的那个玩家。他的浏览器在这场对局中的身份不再是普通客户端,而是货真价实的"权威服务器":伤害结算、碰撞判定、死亡与复活、回合推进、比分统计,全部由房主最终裁定。其余玩家看到的世界,本质上是房主所认定的世界的投影。
熟悉电竞的读者会发现,这个思路和局域网时代《魔兽争霸》《星际争霸》的"主机"一模一样:联机房间里总有一个人是 Host,他的机器就是这场比赛的真理之源。区别只在于,《苍穹对决》把这套机制从局域网搬到了 WebRTC 上——没有局域网,玩家们隔着公网直连,但"围绕一个权威组建世界"的骨架分毫未动。被验证了二十年的模型,不需要发明第二次。
二、星型拓扑:只连房主一个人
裁判有了,连接结构怎么设计?如果 10 个玩家两两直连(全网状),需要维护 45 条连接:每个人的上行带宽被放大数倍,任何一条链路抖动都会让"每个人看到的世界"出现裂缝。《苍穹对决》改成星型:所有玩家只与房主建立一条 WebRTC 连接,玩家之间互不直连。
这样一来,5v5 对局里房主维护 9 条连接,其余每个玩家只维护 1 条——连接数从 O(n²) 骤降到 O(n)。房主收到所有人的状态,汇成一张全景图,再广播回去。整个对局像一个小小的"世界"围绕着房主旋转——这就是"房主小世界"这个名字的由来。下面的架构演示图是可交互的,可以直观看到所有玩家如何围绕房主组网:
三、房主的一天:20Hz 里的权威工作流
房主和普通玩家之间的一切通信都遵循一个固定节拍——20Hz,即每秒 20 个来回:
- 非房主玩家:每秒 20 次把自己的操作与状态(upd)上报给房主;同时接收房主广播的权威快照(sync),把房主认定的世界覆盖到本地。
- 房主:收集所有人的 upd,在本地的"权威世界"里跑完整套结算——飞行物理、命中判定、碰撞、环境伤害——然后每秒 20 次把权威快照发给所有人。
快照走的正是上一篇说的 state 不可靠通道:丢一帧无所谓,50 毫秒后必有更新。而死亡、回合切换、比分这些关键裁定走 event 可靠通道,一次都不能丢。
顺便回答一个常见疑问:为什么是 20Hz 而不是 60Hz?人眼对"别人飞机怎么动"的感知远没有对自己的操作敏感——自己的飞机由本地渲染 60 帧,别人的飞机靠 20Hz 快照插值出来,视觉上已经足够顺滑。而带宽是刚性的:5v5 每秒 20 次全量状态广播,10 个人的上行流量已经不小,频率翻倍只会让家庭宽带的房主率先崩溃。在自己的带宽预算内,把最关键的信息按时送到——频率的选取本质上是一场工程权衡,而不是技术炫技。
四、开火与子弹:从上报到广播
一个具体例子:非房主玩家扣下扳机时,本地并不直接生成一颗"算数"的子弹,而是上报一个 fire 意图。房主收到后,在权威世界里生成子弹、赋予弹道,随后用 blt 消息广播给全场——包括开火者自己。开火者收到自己那颗子弹的 blt 时会跳过生成(防止本地预生成导致的双份子弹)。
为什么要绕这一圈?因为子弹是否命中必须由房主裁定。如果每个客户端都自己算弹道,同一颗子弹在不同设备上会命中不同的目标。弹道由房主统一生成、统一推进、统一判定,全场看到的命中结果才严格一致。开火者本地那颗"预显示"的子弹只是视觉演出,它的账怎么平——正是下一篇文章的主题。
五、掉线判罚:规则简单粗暴
P2P 对局里,断线不是"如果"而是"何时"——手机锁屏、地铁进隧道、家里路由器重启,都会随时掐断一条连接。所以掉线处理必须在设计之初就想清楚,而不是出事后再打补丁。《苍穹对决》的规则只有两条:
- 房主掉线:世界没了裁判,比赛无法继续——全员立即弹窗判负,比赛结束。没有"等待房主重连"的复杂状态机,规则粗暴但毫不含糊。
- 非房主掉线:房主权威判定其死亡并广播 peerGone,剩余玩家继续打完。比分、回合、奖励照常结算。
为什么房主掉线不做重连?因为"房主的世界"就活在房主那台设备的内存里——他一关浏览器,这个世界的所有运行时状态(子弹、血量、回合进度)就消失了。要做断线重连,就得把这些状态序列化并迁移到另一台设备上,复杂度呈指数上升;而一个 5 局 3 胜的对局通常不过十几分钟,重开一局的成本远低于把重连机制做对的成本。把复杂度砍掉,把规则说清楚——这同样是设计决策,而且是更难的那种。
六、代价与对策:房主也是普通家庭宽带
这套设计当然有代价:房主承担全部结算压力,房主的上行带宽决定全场体验的下限;房主自身的延迟不会因为"他是服务器"而消失。对策有三层:星型拓扑把房主的负担压到 O(n);命中判定时跳过过期上报(延迟补偿,详见下一篇);以及最关键的——本地预判 + 权威回溯,让每个玩家即使隔着几百毫秒的链路,手感依然跟单机一样。
还有一条常被忽略的软性对策:让房主成为一个荣誉而不是负担。创建房间的人天然是这局的组织者,掉线判负的规则让房主有动力选一个网络稳定的环境开局;而作为补偿,房主享受着全场最低的延迟(他到自己永远是 0ms)和最完整的战场信息。权责对等,是这套架构能被玩家自然接受的隐形前提。