门后无尽开发日志
07/1240 浏览开发日记
# 《门后无尽》近期联机与排行榜修复开发日志
大家好,这里是《门后无尽》的开发记录。
这段时间我主要集中修复了两个一直影响体验的问题:
1. 联机匹配、房间、结算偶发异常
2. 排行榜昵称、数据持久化和显示不稳定
这两个问题都不是单点 bug,而是随着真实玩家测试逐渐暴露出来的一整套链路问题。中间反复修了很多次,也踩了不少坑,所以这次想把整体修复过程和思路记录一下。
---
## 一、联机问题:从“能匹配”修到“稳定开局、稳定结算”
最开始联机的问题看起来比较简单:玩家有时候匹配不到真人,或者两个人明明差不多同时点了匹配,却进不到同一局。
但后来测试发现,问题远不止“匹配池没配上”这么简单。
### 之前出现过的问题
联机系统中陆续出现过这些情况:
- 两个玩家短时间错开点击匹配,可能配不到一起;
- 玩家还没真正进入游戏,服务端就认为他已经在局内;
- 某些玩家没有进入游戏,但对局结束后却被带进结算页;
- 旧房间、旧匹配状态残留,导致下一局里出现上一局玩家的假人;
- 房间结束后没有及时清理,影响下一次匹配;
- 普通匹配、排位匹配、公开房间、私密房间之间的状态互相污染;
- 有时重复收到开局事件,客户端会被重新拉回出生点;
- 匹配取消、退出、断线后,服务端和客户端状态没有完全同步清干净。
这些问题的根源是:
早期联机逻辑里,“玩家发起匹配”“玩家确认准备”“客户端收到开局”“玩家真正进入游戏”“玩家参与结算”这些状态没有完全分开。
一旦网络事件延迟、玩家退出、房间残留或者设备响应慢,就容易出现服务端和客户端对“这个玩家到底有没有真正入局”的认知不一致。
---
## 二、联机匹配是怎么修的
这次修复后,联机匹配不再简单依赖客户端反复发送房间号,也不再直接用旧房间复用逻辑硬凑玩家,而是改成了更明确的服务端权威队列。
### 1. 自动匹配改为服务端 Ticket 队列
现在普通匹配和排位匹配都会先进入服务端的匹配 Ticket 队列。
每个玩家发起匹配时,服务端会记录:
- 匹配类型:普通 / 排位;
- 对局人数;
- 模式参数;
- 玩家身份是否就绪;
- 客户端是否已经准备好;
- 发起匹配的时间。
只有同规格、身份有效、状态正常的玩家,才会被服务端归到同一个匹配桶里。
这样可以避免旧逻辑里出现的情况:
玩家 A 还挂在旧房间里,玩家 B 新开了匹配,结果服务端把两个人错误地塞到一起。
### 2. 正式房间只在配对成功后创建
以前为了让短时间错峰匹配更容易成功,尝试过“预选房间”逻辑。这个方案短期有效,但会带来房间残留、旧房间污染等副作用。
现在改成:
- 排队阶段只保存 Ticket;
- 不提前创建正式房间;
- 只有凑够符合条件的玩家,或者达到 AI 补位条件时,才创建正式 room;
- 房间创建后再进入准备和开局流程。
这样房间生命周期更干净,匹配池也不会被旧房间号污染。
### 3. 开局拆成两阶段确认
现在联机开局不是服务端一发 RoomStart,客户端就立刻进游戏。
而是分成两步:
第一步:服务端发送“预启动通知”
客户端收到后,只回复 ACK,表示“我收到了开局通知”。
第二步:服务端确认所有有效玩家都 ACK 后,再发送“正式开局确认”
客户端只有收到正式确认,才真正进入游戏。
这解决了一个关键问题:
以前有些玩家其实没进游戏,但服务端已经把他当成参赛玩家,最后导致结算异常。
### 4. “真正入局”单独确认
现在服务端不会因为玩家 ACK 了开局通知,就认为他已经进游戏。
玩家必须在当前 MatchId 下发出有效的游戏状态包,服务端才会把他标记为“真正入局”。
也就是说:
- 收到匹配请求 ≠ 入局;
- 点了准备 ≠ 入局;
- 收到开局通知 ≠ 入局;
- 只有真正进入游戏并同步状态后,才算入局。
最终结算也只会发给真正入局的玩家。
这修掉了“没进游戏却被结算”的问题。
### 5. 每一局加入 MatchId 隔离
联机房间现在会为每一局生成独立 MatchId。
所有会改变游戏状态的网络事件,例如:
- 开局;
- 玩家状态同步;
- 地图同步;
- 过门;
- 死亡;
- 结算;
都必须携带并校验 MatchId。
如果客户端收到旧房间、旧对局、旧网络包的事件,会直接忽略。
这主要解决了常驻服务环境里最麻烦的一类问题:
旧事件延迟到达,误改当前对局状态。
### 6. 房间结束后增加兜底清理
联机结算后,服务端现在会对已结束房间做延迟清理。
清理内容包括:
- 玩家与房间的绑定;
- 房间成员残留;
- QuickMatch 状态;
- 已 finished 的房间元数据。
但不会清理仍在等待、准备或进行中的房间。
这样可以避免上一局结束后,旧成员残留到下一局,导致看到上一局玩家 ID 或原地不动假人的情况。
### 7. 公开房和私密房与自动匹配彻底分离
现在公开房、私密房和自动匹配的状态不会混用。
- 公开房只出现在搜索房间列表;
- 私密房只能通过邀请码加入;
- 自动匹配只走匹配 Ticket;
- QuickMatch 不会再收编公开房;
- 创建或加入手动房间前,会清理自动匹配状态。
这样可以避免“创建了公开房却搜不到”“私密房被匹配池污染”“自动匹配把手动房间状态带走”等问题。
### 8. 搜索房间页增加自动刷新
房间搜索页现在会在页面打开时自动静默刷新。
如果另一台设备创建了公开房,搜索页不需要频繁手动点刷新,也能在短时间内看到新房间。
同时自动刷新只在房间搜索页生效,不会影响匹配中、房间大厅或正在游戏的状态。
---
## 三、排行榜问题:从“能显示”修到“离线也能保留真实昵称”
排行榜的问题也修了很多轮。
一开始表现为:
- 当前玩家自己的名字有时能显示;
- 其他玩家经常显示成 TapTap 玩家、数字 ID 或“昵称加载中”;
- 玩家在线时排行榜名字可能是对的;
- 玩家下线后又变回默认名;
- 有些榜单刷新时会疯狂闪烁;
- 多个榜单同时请求昵称,导致加载慢、显示不稳定;
- 排行榜数据本身和昵称显示链路混在一起,导致修一个地方又影响另一个地方。
### 核心问题
排行榜分数和玩家昵称不是同一个问题。
分数可以存在榜单里,但昵称可能来自:
- TapTap 当前在线昵称查询;
- 客户端本地缓存;
- 服务端在线玩家信息;
- 云榜附加字段;
- 旧版 fallback 名称;
- 系统默认编号。
如果只靠在线查询昵称,那么玩家一下线,排行榜就可能重新变成默认名称。
所以后面修复的核心方向是:
不能只在 UI 层临时查昵称,而是要把真实昵称稳定持久化。
---
## 四、排行榜是怎么修的
### 1. 增加排行榜昵称持久化
现在玩家拿到真实授权昵称后,会把昵称写入独立的排行榜资料字段。
也就是说,排行榜不再只依赖临时在线查询。
当玩家下线后,其他玩家查看排行榜时,依然可以优先读取云端保存过的真实昵称。
### 2. 增加独立的云端画像锚点
为了防止旧字段被默认名污染,现在增加了独立的排行榜 profile 数据。
读取昵称时会按优先级选择:
1. 云端 profile 里的真实昵称;
2. 旧版持久化昵称字段;
3. TapTap 昵称接口返回值;
4. 在线玩家状态;
5. 最后的中性 fallback。
这样能避免玩家离线后名字又退回 TapTap 默认编号。
### 3. 过滤系统默认昵称
排行榜现在会识别并过滤很多占位名和默认名,例如:
- 纯数字;
- TapTap玩家 + 数字;
- 玩家 + 数字;
- 用户 + 数字;
- 游客 + 数字;
- Player / User + 数字;
- ID 字符串;
- 昵称加载中;
- 昵称同步中。
这些名字不会被当成真实昵称写入云端,也不会覆盖已经保存过的真实名称。
这样可以避免“默认编号把真实昵称覆盖掉”。
### 4. 服务端也会回写真实昵称
以前主要依赖客户端同步昵称,但这样不稳定。
现在服务端在多个时机拿到真实昵称时,也会主动写回:
- 玩家身份确认时;
- 客户端状态同步时;
- 排行榜提交分数时;
- 服务端读取排行榜并查到真实昵称时;
- 在线玩家信息可用时。
即使玩家分数没有变,只要昵称是真实有效的,也可以单独更新昵称资料。
这样解决了“分数没提升,所以昵称也没机会更新”的问题。
### 5. 排行榜昵称查询做了缓存和节流
之前排行榜闪烁、加载慢,很大一部分原因是多个榜单同时查同一批用户昵称。
现在做了这些优化:
- 已有数据时不再整页显示“加载中”;
- 刷新时保留旧列表,只显示轻量刷新状态;
- 同一个 userId 的昵称查询会缓存;
- 短时间内不会重复查询同一个玩家;
- 查询结果会回填到实际显示的榜单数据里;
- 查询失败会延迟重试,而不是永久停在加载中。
最终效果是排行榜不会再因为后台刷新而疯狂闪烁。
### 6. 兼容不同云榜返回格式
云榜返回的数据里,有时 userId 不在固定字段里,可能出现在 `userId`,也可能出现在 `player`,甚至不同接口返回结构不一致。
这次修复也补了兼容逻辑,避免把数字型 player 错误当成历史昵称。
这类问题以前会导致:
明明有用户 ID,却没有正确拿去查昵称,最后只能显示 TapTap玩家或 fallback。
---
## 五、排位和结算也一起做了回归检查
联机和排行榜修复期间,我也反复检查了排位积分链路,避免修匹配时把排位加分修坏。
目前排位结算仍然保持:
- 真实联机对局结束后才结算;
- 只对真正入局的玩家结算;
- 服务端 MatchEnd 会参与胜负判定;
- 排位分通过原有赛季积分链路写入;
- 赛季榜和普通排行榜分离;
- 匹配异常、未入局、旧 MatchId 的事件不会触发错误结算。
---
## 六、这次修复后的重点变化
简单总结一下,现在的联机和排行榜相比之前主要稳定在这些点:
### 联机方面
- 自动匹配改为服务端权威 Ticket 队列;
- 普通匹配、排位匹配、公开房、私密房状态分离;
- 房间只在真正配对成功后创建;
- 开局分为 pending 和 confirmed 两阶段;
- 玩家必须真正进入游戏后才参与结算;
- 每局都有 MatchId,旧事件不会串到新局;
- 重复 RoomStart 不会重置地图和出生点;
- 结束房间会延迟兜底清理;
- 搜索房间页支持自动刷新;
- 匹配取消、退出、断线会更完整地清理状态。
### 排行榜方面
- 真实昵称会写入云端持久化字段;
- 离线玩家昵称不再依赖临时在线查询;
- 过滤 TapTap 默认编号和各种占位名;
- 服务端也会主动回写真实昵称;
- 排行榜刷新不会整页闪烁;
- 昵称查询做了缓存、节流和失败重试;
- 四类榜单的数据与昵称显示链路更稳定;
- 排行榜不再轻易显示纯数字 ID 或“昵称加载中”。
---
## 七、后续计划
联机和排行榜属于长期稳定性问题,单次修复很难靠“看起来能跑”就完全确认。
所以接下来我会继续重点观察:
- 双设备普通匹配是否稳定进同一局;
- 排位匹配错峰点击时是否正常配对;
- 房间创建、搜索、加入、退出是否有残留;
- 结算后重新匹配是否还会出现旧玩家假人;
- 玩家下线后排行榜昵称是否仍能保留;
- 排行榜刷新时是否还有闪烁或长期加载;
- 排位积分和赛季榜是否持续正常更新。
如果大家遇到新的联机异常、排行榜显示异常,欢迎继续反馈。最好能附带发生场景,比如:
- 普通匹配 / 排位匹配 / 公开房 / 私密房;
- 是否两台设备同时点击;
- 是否有人中途退出或杀进程;
- 异常发生在匹配中、房间中、游戏中还是结算后;
- 排行榜是哪一个榜单显示异常。
这些信息会非常有助于定位问题。
---
这次联机和排行榜修复反复做了很多轮,主要目标不是“临时绕过去”,而是把底层状态链路理顺。
感谢大家这段时间的测试和反馈。
《门后无尽》会继续修,继续打磨。
因为匹配池和排行榜才修复完毕,还是有点不稳定和完美,后续会持续优化。





