笃行
首页
个人 & 心法
互联网/硬件后台
游戏基础架构
UE 引擎
游戏业务
AI / 大模型
数据结构与算法
机器学习数学
通用基础
GitHub
首页
个人 & 心法
互联网/硬件后台
游戏基础架构
UE 引擎
游戏业务
AI / 大模型
数据结构与算法
机器学习数学
通用基础
GitHub
  • 游戏业务实现(6 年)

    • 游戏业务实现
    • 多模板游戏活动框架
    • 赛事玩法(Bracket / 瑞士轮 / BO 系列)
    • 业务幂等性设计
    • 跨渠道限购与游戏侧分布式事务落地
    • Redis 房间推荐列表
    • 排行榜 / 榜单
    • 抽卡 / 掉落与保底
    • 邮件 / 发奖补偿
    • 匹配 / 段位(MMR)
    • 游戏反作弊
    • 游戏经济与成长
    • 游戏与互联网后台的本质差异
    • 业务代理 · 支付 · 商城

赛事玩法(Bracket / 瑞士轮 / BO 系列)

赛制建模 · 种子分配 · 比分晋级 · 录像回放 · 观战低延迟推流 · 反作弊闭环——用一套赛制骨架把电竞级玩法配置化上线。

一句话结论

赛事 = 赛制模型(Bracket / 瑞士轮 / 循环)+ BO 系列把胜负算清楚 + 种子分配让强者不打架 + 观战延迟预算(HLS ~10s / LL-HLS ~2s / WebRTC ~500ms)压反作弊窗口 + 确定性录像兜住重赛判定。匹配 / 反作弊 / 活动模板 / 网络低延迟四大能力靠交叉链接引用,本篇讲赛制骨架。

本篇的红线:不重复展开

  • 匹配算法(MMR / ELO / Glicko / 扩圈搜索)详见 matchmaking,本篇只讲赛事场景下的种子分配与队伍对齐。
  • 服务端权威与遥测评分详见 anti-cheat,本篇只讲赛事期加强层与重赛判定。
  • 条件-进度-奖励三段抽象详见 activity-framework,本篇只讲赛事作为一种活动模板的接入方式。
  • 端到端延迟预算与网络栈详见 net-lowlatency-fullstack,本篇只讲观战直播的延迟档位。

场景问题

普通匹配和赛事玩法看着都在"给玩家凑对手",其实是两回事:

维度普通匹配(matchmaking)赛事玩法
目标快 + 公平公平 + 可观赏 + 可复现
参与人数池子里的散人已注册的固定队伍/选手
匹配方式MMR 扩圈搜索按赛制模型(Bracket / 瑞士 / 循环)+ 种子
一局出结果一句话BO3/BO5/BO7,含 Bye / Tie-Breaker / 断线补赛
观战可选、不做也行必选,且延迟档位有商业约束
录像玩家自愿必留,用于争议判定与转播
反作弊常态赛事期加强 + 重赛判定 + 申诉

三个真实的赛事事故

  1. BO5 断线补赛歧义:BO5 打到 2:2 决胜局,一位选手中途断线。规则说"重开当前局",但比分是保留还是清零?没写清就成撕逼。
  2. 观战延迟太短反噬反作弊:观战延迟 500ms 时,选手可能通过队友直播窥屏——这就是"直播延迟窗口"= 反作弊窗口的边界。
  3. 录像回放的"随机不复现":确定性回放依赖同一随机种子和同一输入序列。赛后申诉时录像跑出不同结果,判定成了黑箱。

赛事玩法开发的核心不是"再写一遍匹配代码",而是把赛制骨架做成配置化模板:赛制种类 + BO 层数 + 种子规则 + 观战档位 + 录像格式 + 反作弊策略 → 一次上线支持后续 N 种赛事。

实现方案

一:赛制模型对比

赛制一句话场次数公平性时长典型场景
单败淘汰(Single-Elimination)输一场就出局N-1(N=选手数)低(1 败=出局,看运气)最短8/16 强淘汰赛
双败淘汰(Double-Elimination)输一场进败者组,再输才出局~2(N-1)高(给败者复活机会)中电竞主流决赛
循环赛(Round-Robin)每对选手都打一场N(N-1)/2最高最长联赛小组赛(8 队以内)
瑞士轮(Swiss)每轮按当前战绩配对,同战绩避免重赛R 轮(通常 ⌈log₂N⌉+1)中高(不用全打完)中大规模选手(棋类、卡牌、CS 起源)
积分赛(League)长期积累,赛季末结算可配置高(大样本平均)最长职业联赛全年

BO 系列(Best-of-N)是每场的层级,正交于赛制模型:

BO 层数决胜阈值场次上限典型
BO11 胜1小组赛 / 大众预选
BO32 胜3常规淘汰
BO53 胜5半决赛 / 决赛
BO74 胜7电竞顶级赛决赛

赛制正交组合

"单败淘汰 + BO3"、"双败淘汰 + BO5"、"瑞士轮 + BO3"——赛制模型和 BO 层数正交,赛事框架应支持同一场赛事内上下阶段用不同组合(如小组瑞士 BO1、淘汰双败 BO5)。

二:Bracket 数据模型

对局树 = 节点(Match)+ 胜/败方链接:

type Match struct {
    ID          uint64
    Round       int              // 轮次(1 = 首轮)
    Bracket     BracketSide      // WINNERS / LOSERS / FINAL
    P1, P2      *Player          // 双方;Bye 时其一为 nil
    BestOf      int              // BO1/3/5/7
    Score       [2]int           // 双方比分(局数)
    Status      MatchStatus      // PENDING / IN_PROGRESS / DONE / WALKOVER
    WinnerNext  *Match           // 胜者进入哪场
    LoserNext   *Match           // 败者进入哪场(双败才有)
    StartAt     time.Time
    ReplayIDs   []uint64         // 关联录像 ID 列表
}

Bye(轮空)处理:选手数不足 2^k 时,前几名种子直接进下一轮。Bye 的对手 nil → Status = WALKOVER,不计入胜负记录,但必须留 Bracket 位(否则种子编号会错)。

Tie-Breaker(并列名次决胜):循环赛/瑞士轮的常见问题,按优先级依次比较:

  1. 直接对局胜负(Head-to-Head)
  2. 净胜局数(Game Win Ratio)
  3. 总局分(Points)
  4. 公共对手的强度(Buchholz / SOS,瑞士轮常用)
  5. 抛硬币 / 表演赛(真正最后手段)

断线补赛

  • 局内断线(BO 内的一小局):约定"5 秒内重连则继续",否则该局判负;比分保留(重开的只是当前局)。
  • 对局间断线(一小局已结束,下一局未开):延时 X 分钟后判该场剩余局全负;已打完的局比分保留。
  • 不可抗力(服务器故障 / 断网):WALKOVER 或 REPLAY_LATER,走申诉走复盘流程,不由选手主张。

关键:这三种边界必须赛前公示,事后再定就是撕逼。

三:种子分配

种子(Seeding)= 让强者不在早期相遇。三种典型:

方式规则优点缺点
Seed by rating按 MMR/积分从高到低编号,1 号种子对末号种子强者晚遇头部相互伤害风险大
Snake seeding(S 型)分组时蛇形:A 组[1,4,5,8],B 组[2,3,6,7]分组均衡计算稍复杂
Random within tier分档次(Tier 1/2/3),档内随机保观赏性 + 避免弱队反复被虐需要合理档次线

跨赛区队伍的时区与延迟约束:

  • 队伍所在赛区 → 服务器选择要能双向可接受(不能让一方 RTT 200ms+,详见 net-lowlatency-fullstack)。
  • 时区差大的场次(如中美对阵)要在双方都不深夜的窗口安排;不行就先协商中立时区。
  • 涉及签证/隔离期的线下赛还要预留 D-14 排期。

四:录像回放

确定性回放依赖:同一随机种子 + 同一输入序列 + 同一版本代码/数据。三者缺一,回放就"跑不出一样"。

  • 格式:种子 + 版本 hash + 输入序列(按帧压缩)+ 关键帧快照(每 N 秒一份)。
  • 快照点:既是回放起点(跳转 / 倍速播放的基础),也是灾难恢复点——一局打到一半服务端崩了,从最近快照回放 + 重放输入即可恢复(与 stateful-recovery 的 checkpoint + WAL 同思路)。
  • 跳转与倍速:从快照 A 直接跳到快照 B 之间的任意帧,靠回放引擎快进。倍速播放不改物理,只改渲染节奏。
  • 隐私脱敏:观战版本要去掉聊天、语音、账号信息;比赛版本可保留但归档时脱敏。

帧同步 vs 状态同步 的录像取舍

  • 帧同步(同步输入):录像文件极小(只存输入序列 + 种子),但必须代码/数据版本完全一致才能回放;一次热更就让老录像"失效"。
  • 状态同步(同步状态):录像文件大(存关键帧全状态),但跨版本可放(服务端把状态还原到客户端渲染即可)。
  • 赛事一般选帧同步 + 版本冻结:赛期内代码不允许热更,录像永久可回放;平时用户版本用状态同步。

五:观战低延迟推流

观战不是"直播 + 拉流",是延迟档位与业务规则的交易:

档位延迟反作弊窗口典型协议适用
无延迟观战(服务端直接推)~50–200ms极小私有 UDP赛事导播台内部
超低延迟直播~500ms小WebRTC高价值付费观赛
低延迟直播~2s中LL-HLS / CMAF主流直播
常规直播~10s大HLS / DASH大众平台推流

观战延迟与反作弊窗口的悖论

观战延迟越短,"选手通过队友直播窥屏"的时间窗口越小,但推流成本、抖动/丢包容忍度、卡顿感都变差。所以:

  • 官方直播通常主动加 10–30 秒延迟("直播延迟窗口" = 反作弊窗口);
  • 导播台内部用无延迟观战做及时判断;
  • 付费高观感套餐用 WebRTC 但限流量白名单,防止外挂利用超低延迟窥屏。

推流节点就近调度:详见 net-lowlatency-fullstack 的 GeoDNS / Anycast + BGP 章节,本篇不复述。

六:反作弊闭环

赛事期的反作弊在常态基础上加强,四步闭环:

  • 常态:详见 anti-cheat(服务端权威、遥测评分、封禁申诉闭环)。
  • 加强:赛事期开启关键操作服务端二次校验(比如"击杀判定"服务端复算而不是采信客户端)、录像强留、人工导播实时监控。
  • 申诉窗:封禁后 24/48 小时可申诉,走独立评审组,避免误杀退赛。
  • 赛后重赛判定:如果作弊被赛后确认(比如通过录像人工审核发现的开镜),要按赛前公示的规则判负 + 名次顺延或重赛。

七:作为一种活动模板接入

赛事本质是条件-进度-奖励三段抽象的一种实例(详见 activity-framework):

  • Condition:报名条件(等级/段位/绑定要求)
  • Progress:赛程进度(当前轮次 / 已完成场次 / 战绩)
  • Reward:名次奖励、参与奖励、单场胜利奖励

复用活动框架的好处:幂等发奖、断线补发、防重复领取、多渠道对账这些通用能力不需要重写。

为什么这么做

  • 为什么把赛制模型和 BO 层数拆成两层正交:真实赛事经常"小组瑞士 BO1、淘汰双败 BO5、决赛 BO7"多种组合叠加。拆开后配置化上线一次赛事只是配几个参数,不用重写代码。
  • 为什么种子必须走 MMR/积分而不是随机:随机分配头部选手会导致 1 号种子第一轮就撞 2 号种子,头部相互伤害、观赏性崩盘。种子的意义就是用赛前信息把强者晚遇作为约束。
  • 为什么录像必须确定性回放:赛后申诉需要"客观回放"这一板凳。若回放跑出不一样的结果,判定成黑箱,权威性崩塌。
  • 为什么观战要主动延迟 10–30 秒:反作弊的边界就是"选手看不到实时对手信息"。观战延迟越短,作弊窗口越小;但官方直播主动加大延迟是最便宜的反作弊手段之一。
  • 为什么赛事复用活动框架:报名、发奖、进度、公示、防重复——这些能力在活动侧已经沉淀过一遍,赛事再自造轮子只会踩同样的坑(重复发奖、少发奖、断线补发丢失)。

为什么别的选择不行

  • 只用普通匹配代替赛制:匹配面向"池子里的散人",赛事面向"已注册的固定队伍"。前者要"快",后者要"公平 + 可观赏 + 可复现",目标函数不一样。
  • 单败淘汰做重要赛事:一败即出局,头部选手被冷门爆冷就整场赛事看点全无。双败给败者一次复活机会,是电竞主流决赛选择。
  • BO1 做决赛:偶然性太大,观众和选手都不服。决赛用 BO5/BO7 拉长样本,降低方差。
  • 观战延迟不加:作弊窗口太大,被利用一次就是重大公关事故。
  • 录像用状态同步:文件大 10-100 倍、成本爆炸;且状态同步的"跨版本可回放"优势在赛期(版本冻结)用不上。
  • 赛事期不加强反作弊:常态反作弊的评分阈值是"错杀 vs 漏杀"的平衡;赛期"漏杀"的代价是奖金,必须调高召回宁可增加人工复审。

三个赛前必须公示的规则

  1. 断线补赛规则:局内断线、局间断线、不可抗力三种边界的判定;
  2. Tie-Breaker 顺序:哪个指标优先,抛硬币是不是终极手段;
  3. 申诉窗口与判定权限:申诉多长时间内有效,评审组是谁,是否可能重赛。

赛前不公示,事后必撕逼。

沉淀结论

  • 赛事骨架 = 赛制模型(Bracket / 瑞士 / 循环)× BO 系列,两层正交组合配置化上线。
  • 种子分配让强者晚遇:Seed by rating、Snake seeding、Random within tier 三种选一,避免头部互伤。
  • Tie-Breaker 优先级:直接对局 → 净胜局 → 总局分 → Buchholz → 表演赛,必须赛前公示。
  • 录像:确定性回放(种子 + 版本 + 输入序列),赛事期锁版本用帧同步。
  • 观战延迟是反作弊窗口:官方直播主动加 10–30s,导播台用无延迟,付费白名单用 WebRTC。
  • 赛事反作弊在常态基础上:关键操作服务端复算 + 录像强留 + 人工监控 + 申诉/重赛闭环。
  • 接入 activity-framework 复用报名/发奖/进度/公示能力,不自造轮子。

记忆口诀

赛制两层:模型(单败/双败/循环/瑞士/积分)× BO(1/3/5/7)——正交组合
Bracket 三要素:Match 节点 / 胜败方链接 / Bye + Walkover 保位
Tie-Breaker 五级:直接对局 → 净胜局 → 总局分 → Buchholz → 表演赛
种子三法:Seed by rating / Snake seeding / Random within tier
观战四档:50ms 导播 / 500ms WebRTC / 2s LL-HLS / 10s HLS
反作弊四步:加强遥测 → 服务端复算 → 人工复审 → 判负/重赛/申诉
赛前三公示:断线补赛边界 / Tie-Breaker 顺序 / 申诉窗与权限——不公示必撕逼
录像三要素:随机种子 + 输入序列 + 版本冻结——缺一回放不复现

内容来源

综合整理。参考方向:Riot Games / Valve / Blizzard 官方电竞赛制文档、Challonge / Toornament 等赛事平台的数据模型公开信息、瑞士轮 Buchholz 分数在国际象棋联合会(FIDE)的定义、直播协议 HLS / LL-HLS / WebRTC 的延迟规范,以及站内 matchmaking / anti-cheat / activity-framework / net-lowlatency-fullstack 的赛事场景应用视角。

自测:合上资料能说清楚吗?

Q1: 一次八强淘汰赛,双败 + BO5,选手 8 位;打完 Winners Finals 后 Bracket 长什么样?
  • Round 1(胜者组):4 场 BO5(1 对 8、4 对 5、2 对 7、3 对 6,按种子)
  • Round 2(胜者组 = Winners Semifinals):2 场 BO5,四位胜者相遇
  • Winners Finals:1 场 BO5,胜者进 Grand Final
  • 输者进入 Losers Bracket,与前一轮的败者相遇,输一场就 DQ;最终 Losers Finals 胜者进 Grand Final
  • Grand Final:胜者组冠军 vs 败者组冠军,通常 BO5,且胜者组冠军带 1:0 优势(因为它一路没输)

关键数据结构:每个 Match 有 WinnerNext / LoserNext 两个链接,胜者进胜者组下一场、败者进败者组对应场。

Q2: 瑞士轮 16 人,几轮打完?为什么可以少打?

⌈log₂16⌉ + 1 = 5 轮。瑞士轮的核心:每轮按当前战绩配对,同战绩之间打——⌈log₂N⌉ 轮之后战绩已经充分区分(数学上等价于二分收敛),无需像循环赛一样全打完 N(N-1)/2 = 120 场。Buchholz(对手强度总分)用于同战绩之间的 Tie-Breaker。

Q3: BO5 打到 2:2,决胜局一位选手断线,怎么判?

按赛前公示的规则:

  • 局内断线(决胜局刚开 30 秒断的):约定 5 秒内重连则继续,否则该局判负 → 比分变 2:3,对方胜。已打完的 2:2 保留,不清零。
  • 服务器故障:REPLAY_LATER,走申诉复盘,不由选手主张。

关键在赛前公示:规则事前定好,事后按规则动作。规则不公示,事后再定就是撕逼。

Q4: 为什么官方直播主动加 30 秒延迟?不加更好看不好吗?

"直播延迟窗口" = 反作弊窗口。观战延迟越短,选手通过队友直播窥屏、外挂利用直播信息作弊的窗口越小。但直播延迟太短会:

  • 推流成本高(WebRTC 每路成本远高于 HLS);
  • 卡顿感明显(网络抖动更容易感知);
  • 给作弊留窗。

主动加 10–30 秒延迟是最便宜的反作弊手段——外挂能拿到的信息永远比选手本人晚 30 秒。导播台用无延迟给解说、付费高观感用 WebRTC 白名单、大众直播用 HLS 10s 兜底,是三档并行的方案。

Q5: 帧同步录像和状态同步录像各有什么优劣?赛事选哪种?
  • 帧同步录像:只存随机种子 + 输入序列(每帧压缩),文件极小(一局几十 KB);但必须代码/数据版本一致才能回放,一次热更让老录像失效。
  • 状态同步录像:存关键帧全状态(每 N 秒一份),文件大 10–100 倍;但跨版本可回放(服务端还原状态到客户端渲染即可)。

赛事选帧同步 + 版本冻结:赛期内代码不允许热更,录像永久可回放,同时享受小文件优势。平时的用户版本用状态同步跨版本更灵活。

Q6: 赛事反作弊比日常反作弊多做什么?

在常态(服务端权威 + 遥测评分 + 封禁申诉,详见 anti-cheat)之上:

  1. 关键操作服务端二次校验:击杀判定、伤害计算、道具使用都在服务端复算(不采信客户端);
  2. 录像强留 + 人工监控:每局录像全留、导播台实时监控可疑动作;
  3. 判罚阈值调高召回:宁可多几个人工复审,也不能漏杀;
  4. 申诉与重赛闭环:24/48 小时申诉窗,赛后作弊确认要按规则判负 + 名次顺延或重赛。
最近更新: 2026/9/10 11:38
Prev
多模板游戏活动框架
Next
业务幂等性设计