跳转到内容

第 44 章 · 内测与日志

约 7 分钟 难度:5 动手章

这一章解决:完整项目进入内测时,如何记录问题、复现问题、判断优先级,并让每次修复都能回到同一张测试矩阵。

先看一下

第 42 章加了敌人和对象池,第 43 章加了体感反馈。项目已经像一局游戏。上线前最容易坏的是「问题无法复现」:谁是 Owner、当时第几局、第几波、谁迟入、对象池是否耗尽、网络是否拥塞,这些信息没有记录,下一天就只能靠猜。

这一章会拿到什么

  • 一份 2 / 4 / 8 人内测矩阵
  • 一套日志字段:matchIdphasewaveIndex、Owner、请求号、结果
  • 一张问题优先级表:阻断、严重、普通、观察
  • Quest 与性能检查的最小流程
  • 上线前停手线:哪些问题必须修,哪些能进迭代

依赖前面

  • 第 7 章的网络 Debug 面板与最小测试矩阵
  • 第 39 章的 Quest 与性能预算
  • 第 42 章的对象池耗尽日志
  • 第 43 章的体感降级规则
  • 创作者视角 8 的上线后迭代视角

内测记录从固定三件事开始:世界版本、测试人数、测试场景。

字段例子用途
worldVersionv0.4.0-mvp对应哪次上传或哪次 Build & Test
testGroup2p-local / 4p-mixed / 8p-public-like对应人数和网络环境
testScenarioowner-leave-wave-2对应复现路径
matchId17对应第几局
buildTargetWindows / Android对应平台

没有这些字段,截图和描述会很快失去上下文。一个「敌人不动了」的 bug,2 人本地、4 人公网、Quest 8 人房的原因可能完全不同。


日志不追求漂亮,追求可查。推荐固定前缀:

[GW][v0.4.0][match=12][phase=INGAME][wave=2][owner=7] event=enemy_killed enemy=3 killer=5 score=14

最小字段如下。

字段来源说明
worldVersion手动常量当前测试版本
matchGameState.matchId当前第几局
phaseGameState.phase当前阶段
waveGameState.waveIndex当前波次
ownerNetworking.GetOwner(gameObject).playerId当前对象 Owner
event手写事件名本行发生什么
requestPlayerObject requestId对应哪次玩家请求
resultaccepted / rejected / corrected裁决结果

代码片段只保留包装函数。

private void LogGame(string eventName, string detail)
{
Debug.Log("[GW][" + worldVersion + "]"
+ "[match=" + matchId + "]"
+ "[phase=" + phase + "]"
+ "[wave=" + waveIndex + "] "
+ "event=" + eventName + " " + detail);
}

GameState、EnemyObject、EnemyPool 都用同一套字段。EnemyObject 可以额外加 enemy=3,PlayerObject 可以额外加 player=5 request=42


第 7 章的五项矩阵继续保留。第八部主项目扩展到三档人数。

人数目标必测场景
2 人验证核心同步Ready、Start、命中、结算、Restart、迟入
4 人验证合作防守默认规模同时攻击、Owner 离开、对象池压力、体感反馈
8 人验证接近公开房压力Quest / 头像 / 网络拥塞 / UI 可读性 / 降级

2 人测试追求确定性:每一步都知道谁按了什么。4 人测试开始看并发:两个人同时攻击同一敌人,Owner 在 wave 2 离开,迟入玩家在 RESULT 加入。8 人测试看压力:同屏头像、对象池、音效、特效、网络事件都叠起来。


每次准备发布前,跑一轮项目级测试。表格里的「实际」栏留给测试时填写。

场景预期实际
1. 2 人正常一局LOBBY → COUNTDOWN → INGAME → RESULT → LOBBY 完整走完
2. 2 人迟入B 在 INGAME 加入,看到当前波次、敌人、分数和剩余时间
3. 2 人 Owner 离开新 Owner 接管,剩余敌人仍可击杀并结算
4. 4 人同时打同一敌人敌人只死亡一次,分数只加一次
5. 4 人对象池耗尽少刷或延迟,日志出现 pool_full,游戏继续
6. 4 人连续重开 3 局matchId 单调递增,旧局敌人和分数不串味
7. 8 人拥塞普通远端特效降级,GameState 和 EnemyObject 状态继续同步
8. Quest / Android 构建主区域帧率、材质、粒子、同屏敌人数量在预算内
9. RESULT 中迟入迟入玩家直接看到结算,不补播旧事件
10. 重开后迟入迟入玩家看到 LOBBY 干净状态,Ready / HP / personalScore 已清

第 4、5、6 行是第八部最容易出问题的地方:并发、池耗尽、跨局残留。每次改 EnemyObject、EnemyPool 或 RestartProjectMatch 都要回归这三行。


内测问题按修复顺序分类。分类标准看「是否破坏一局成立」,不看修起来麻烦不麻烦。

优先级定义例子发布前处理
P0 阻断一局无法完成或会卡死无法结算、重开后无法开始、Owner 离开全局状态丢失必须修
P1 严重状态错误但可重开恢复重复加分、敌人死亡两次、迟入看到错误波次必须修或禁用相关功能
P2 普通体验明显受影响命中特效偶尔丢、UI 倒计时慢一拍可带着上线,列入迭代
P3 观察不确定是否稳定复现某台机器偶现一帧闪烁记录,继续收集

P0 / P1 的共同点是破坏共识状态。P2 / P3 多数在表现层或单次体验层。第 43 章的体感特效丢失通常是 P2;GameState.phase 错乱是 P0。


Quest 检查先从最差视角开始。第 39 章已经给过原则,第 44 章只保留发布前最小步骤。

  1. 在 PC 上打开 Debug View 6,记录 GameState、EnemyObject、EnemyPool 的 BPS 和 Owner。
  2. 在 Android 构建或目标 Quest 设备上进入主区域,观察同屏敌人、粒子、UI 和头像叠加时的帧率。
  3. 把敌人 active 数推到计划上限,观察是否触发对象池降级。
  4. 关闭普通远端命中特效,只保留击杀特效,再测一轮。
  5. 记录「关闭哪些表现后体验仍可接受」。这就是上线降级开关。

VRWorld Toolkit 可以作为可选检查工具,用它看 World Debugger、构建统计和部分资源配置。它不能替代真实多人测试,也不能替代 Quest 真机检查。


上线前要有停手线。否则项目会不断加功能,测试矩阵永远追不上。

第八部主项目的第一版停手线可以这样定:

必须满足可以延后
2 / 4 人完整一局稳定8 人平衡性精调
Owner 离开后能继续或安全回大厅普通命中特效百分百送达
迟入 INGAME / RESULT 视图正确复杂职业和技能树
对象池耗尽不崩更多敌人类型
Quest 构建能进入主区域并完成最小流程长期奖励和排行榜

这条线的意思是:第一版要保流程和状态,内容丰富度留给第 45 章上线后迭代。能上线的最小版本,比功能很多但测试矩阵空白的版本更容易活下去。


挑一条试。

  • LogGame 增加 roomSizeisClogged 字段。跑 4 人测试时,哪些问题更容易被定位?
  • 把项目级测试清单压成「上线前 15 分钟冒烟测试」。哪些行必须保留,哪些行可以放到完整回归里?
场景预期实际
1. 日志字段完整性每条核心日志都含 matchphasewaveevent
2. 2 人完整流程P0 为 0,P1 为 0
3. 4 人并发攻击重复击杀、重复加分、Owner 离开都能定位到日志
4. 8 人压力测试拥塞时表现层降级,状态层继续同步
5. Quest 检查主区域和最差视角都能完成最小一局
6. Bug 归档每个 P0/P1 都有复现路径、版本、日志片段和当前状态
  • 能写出项目日志的最小字段
  • 能区分 P0 / P1 / P2 / P3
  • 能说明 2 / 4 / 8 人测试各自验证什么
  • 能指出 Quest 检查和 PC Build & Test 的差异
  • 能给第一版项目划一条上线前停手线