概念
生命周期
实例四态十一因、玩家八态、对局阶段,以及跨进程那条 trace 怎么把一次匹配串起来。
CrossingNet 里同时存在三种「状态」:对局实例的、玩家的、对局本身的。它们由一个 matchId
和一条 trace 串在一起,日志里能对上。
对局实例
Spawning ──首次健康OK──► Ready ──进人/开局──► Playing
│ │ │
启动超时 空房宽限/关闭 结束(回 Ready 或 Closed)
▼ ▼ ▼
Closed ◄────────────────┴────────────────────┘ (都带 CloseReason)| 状态 | 含义 | 离开条件 |
|---|---|---|
Spawning | 进程已拉起、端口已占,房间还没回健康 | 健康端口回 OK → Ready;StartupTimeoutSeconds(默认 180s)→ Closed |
Ready | 空房间,等人 | 进第一个人 → Playing;空置超过 EmptyGraceSeconds(空房宽限,秒) → Closed |
Playing | 有人的对局 | 房间结束回大厅,实例进 Closed |
Closed | 已关闭,记录保留 ClosedRetentionSeconds(已关闭实例保留,秒) | 过期从表里删 |
十一种关闭原因
ECrossingCloseReason 决定日志里这一局为什么结束,排查时先看它:
| 值 | 含义 |
|---|---|
None | 未指定 |
StartupTimeout | 启动超时 |
SpawnFailed | 进程拉起失败 |
Unresponsive | 健康探测连续失败 |
EmptyRoom | 空房宽限到期 |
OwnerGone | 房主离开 |
Lifetime | 生命周期结束 |
ClosedByOwner | 房主主动关闭 |
StopAll | 全部停止 |
LobbyShutdown | 大厅关闭 |
GameFinished | 对局正常结束 |
玩家
Idle → Queueing → ReadyCheck → Traveling → InRoom → InGame → PostGame → Idle
│ │ │
│取消/超时 │拒绝/超时 │失败(2001 → 回大厅)
▼ ▼ ▼
Idle Idle Idle| 阶段 | 发生了什么 | 失败回哪 |
|---|---|---|
Queueing | 入队,等待配对;窗口随时间放宽 | 取消或超时 6001 → Idle |
ReadyCheck | 配对成功,客户端确认 | 拒绝 6008 / 超时 6007 → Idle |
Traveling | 拿到地址与票据,旅行进房 | 失败 2001 → 回大厅 Idle |
InRoom | 校验票据、分座位、准备 | 房间关闭 → 回大厅 |
InGame | 对局中;掉线保留座位 | 重连窗口内回来 → InRoom |
PostGame | 结算、返回大厅 | — |
对局(比赛)
一局比赛由大厅的 matchId 标识,跨实例迁移时跟着走:
QueueJoin(生成 trace) → MatchFound → ReadyCheck → Assign(带 token 与 trace)
→ Travel → GameStart → EndGame → Settlement → ACK → ReturnToLobbymatchId:配对时生成,结算幂等键trace:入队时生成,经 ReadyCheck、分配 URL(?CrossingMeta=<trace>)一路带到房间, 房间写进PlayerState.CrossingTraceId;房间日志带同一个trace=
用状态对日志
排查一局没走通,按这个顺序看:
1. 大厅 [Match] QueueJoin → MatchFound 真的配到了吗
2. 大厅 [Session] SpawnStart / HealthFirstOK 实例起来了吗
3. 大厅 [Assign] Assigned 分配地址与票据
4. 房间 [Room] JoinTokenAccepted / SeatAssigned 进房成功吗
5. 房间 [Room] GameStart / GameEnd 对局走了吗
6. 大厅 [Session] SettlementRecorded/Acked 结算落盘了吗下一页:大厅与实例。