Metlivi 博客

如何在分支叙事游戏中保持故事的可测试性

当分支叙事故事规模扩大时,应该去测试那些使各路径产生不同表现的决策和状态变化——而不是将每条可能的路线都作为单独的端到端脚本来测试。将叙事建模为一张图(Graph),定义每个决策点的条件与结果,并构建一个覆盖关键转换、汇合点和失败情况的轻量测试套件。接着,采用基于风险的路线抽样和人工游戏测试,来捕捉结构化检查无法评判的问题。这为叙事设计师和 QA 团队提供了一种可复现的缺陷排查方法,而无需声称达到了穷尽的路径覆盖率。

2026年9月27日7 分钟阅读阅读、艺术与文化作者:Metlivi Editorial Team
第 1 节

从记录行为的图模型开始

将每个可玩的段落或场景表示为一个节点,将每个选择表示为一条有向边。在边上标注其前置条件和触发效果:例如,`has_key = true` 会启用“开门”选项,该选项执行后会将 `gate_open = true`。明确标注结局、循环和汇合点。汇合点是指不同路线重新交汇的地方;在这里检查故事是否可以从多种前情历史中继续发展且不携带非预期的残留状态,是非常有效的做法。

该图应当反映游戏实际评估的逻辑,而不仅仅是文本结构。记录某个选择读取了哪些变量、写入了哪些变量,以及后续有哪些节点依赖于这些变量。纳入默认值、重置规则以及任何一次性效果。如果在某个分支中设置了一个标志位且从未被清除,这可能是刻意设计的;将其记录在案能让这一后果变得直观透明,便于审查和测试。

这种结构也有助于定位在冗长脚本中容易被遗漏的决策点。Alexey Tikhonov 在 2024 年发表的一篇论文研究了分支叙事中角色决策点的检测,并提出了一个基于“选择你自己的冒险”(Choose Your Own Adventure)游戏图的数据集。该论文的任务侧重于识别叙事决策点,而非验证某套 QA 方法;它可以为团队如何盘点选择提供参考,但并不证明本文提出的测试方法绝对有效。[Tikhonov, “Branching Narratives: Character Decision Points Detection”](https://aclanthology.org/2024.games-1.8/)

第 2 节

测试状态转换,而不仅仅是场景访问

仅确认节点是否出现的测试可能会漏掉失效的选择。对于每个关键选择,应检查三件事:该选择在预期条件下是否可用;选中它是否会应用预期的状态变更;以及下一个节点和可见结果是否与该状态匹配。这些检查将故事视为一个状态转换系统:给定一个初始状态和一个动作,验证最终的状态和目标走向。

例如,针对选择“出示地图”的测试可以断言:地图已展示、`trust` 保持不变,且路线到达了共用的天文台场景。与其配对的测试则以 `has_map = false` 开始,断言该选择不可用或遵循指定的备选逻辑。具体的预期行为取决于叙事设定规范;重点在于进行显式断言,而不是仅凭段落标题来推断其正确性。

在汇合点,不能只测试是否成功到达。还要对比各条路线原本应该保留、改变或丢弃的状态。在某个分支中被说服的守卫在汇合后可能仍然是盟友,而临时的伪装则应当失效。将这些规则纳入汇合后的预期状态中。如果路线旨在完全融合,就断言其共享状态;如果它们应该保留有意义的差异,也同样要对这些差异进行断言。

第 3 节

使用虚构示例让覆盖范围清晰可见

假设在一个简短的解谜故事中,档案馆处有一个决策点。玩家可以请求帮助、潜入或使用借来的钥匙;每条路线都会到达同一条走廊,随后的一个选择决定了玩家是否拿走一封密封信件。下面的虚构矩阵追踪了一组精简的测试职责。“已覆盖”意味着针对该特定职责规划了测试,并不代表整条路线或每种组合都已被测试。

**A:** `trust = high`;向档案保管员寻求帮助。出现求助选项;`trust` 保持高水平;路线到达走廊。选择可用性与转换

**B:** `trust = low`;寻求帮助。按照设定,求助选项被隐藏或遭到拒绝。负向条件

**C:** `has_key = true`;打开侧门。门被打开;路线到达走廊;钥匙仅在有明确设定时被消耗。状态效果与汇合

**D:** `has_key = false`;尝试开侧门。门无法打开;未设置成功标志位。负向断言

**E:** 从走廊出发,拿走密封信件。`has_letter = true`;后续的证据场景提供该信件专有的台词。下游结果

**F:** 从走廊出发,留下信件。`has_letter = false`;信件专有台词不出现。结果对比与负向断言

这是一个决策辅助工具,而不是覆盖率百分比或通用的最小测试套件。它让疏漏一目了然:在此例中,低信任度门槛和“信件缺失”的结果值得单独检查,因为常规的顺畅流程(happy-path)访问无法验证它们。每一行都应指向图中相应的节点或转换,这样一旦条件发生变化,就能顺藤摸瓜找到受影响的测试。

第 4 节

当组合增多时,优先考虑分支覆盖

如果一个故事包含许多独立的标志位,可能出现的组合数量会呈爆发式增长。切忌将每条理论路线都列为必须完整通关的测试用例。首先应识别高风险的边:决定结局走向、消耗道具、设定长期人物关系事实或合并历史的选择。直接测试这些转换及其关键的下游结果。

然后有针对性地对组合进行抽样。包括边界条件(改变选择所需的临界值)、每个关键条件的正反两面、可能产生交互的标志位的代表性组合,以及通过不同历史背景到达同一汇合点的路线。优先考虑最近修改的内容以及具有复杂前置条件的路径。当两个变量可能产生交互时,为该变量对添加针对性测试,而不要假定单独的单变量检查就能证明组合正常运作。

记录覆盖单元及其局限性。团队可以追踪是否每个关键选择边都得到了执行、相关条件是否均针对 true 和 false 进行了检查,以及每个结局触发器是否至少被一个设计好的测试所触达。这些是对抽样内容的有效报告;但都不能证明所有可能的历史、状态组合或措辞问题都已被排查殆尽。

关于游戏测试的研究可以提供一个相关但边界清晰的思路。Gordillo 等人在 2021 年发表的 arXiv 论文描述了一种强化学习智能体,它通过对新颖动作的奖励来探索复杂 3D 场景中的状态覆盖。该项研究针对的是 3D 游戏环境中的探索,而非分支叙事选择或此处介绍的特定状态转换测试方法。它支持将自动化探索视为一种潜在的补充手段,但该研究与 Tikhonov 的论文都不能直接证明这种叙事测试方法的有效性。[Gordillo et al., “Improving Playtesting Coverage via Curiosity Driven Reinforcement Learning Agents”](https://arxiv.org/abs/2103.13798/)

第 5 节

补充负向断言与人工游戏测试

正向断言用于确认预期的选择或结果确实存在。负向断言则用于确认被禁止的情况没有发生:未解锁的选项不出现、已消耗的线索不会再次发放、缺失的信件不会触发相关台词,或者失败的尝试不会设置成功标志位。负向检查在共享节点周围尤为有用,因为来自另一条路线的陈旧状态很容易泄露到当前场景中。

自动化检查可以验证路线逻辑和精确的状态变更,但无法可靠地判断剧情过渡是否自然连贯、某句台词是否与玩家的记忆产生矛盾,或者某个选择在语境中是否合乎逻辑。因此,人工游戏测试应当有目的地使用挑选出的特定路线:让测试人员走一条冷门分支、带着某种特定经历到达汇合点,或者尝试在缺少关键道具的情况下走向结局。既要观察最终的状态,也要观察玩家对其的理解和感受。

使游戏测试记录与节点及选择标识符挂钩,并附带初始状态和操作步骤。这能确保报告的问题可复现,并有助于区分文案问题与逻辑缺陷。完成修复后,重新运行受影响的状态转换测试,并至少选取一条代表性路线跑通修改后的汇合点或最终结果。

第 6 节

针对变动故事的实用测试周期

每次故事内容更新时,导出或审查图模型,识别发生变动的节点、条件、效果和汇合点,然后更新覆盖矩阵。先运行针对性的状态转换测试;接着对高风险或新修改的章节进行选定路线抽样和人工游戏测试。一旦出现故障,记录其初始状态和选择序列,以便团队能够复现问题、修复相应规则或文本,并将该用例保留为回归测试。

其目标是形成一份清晰记录“测试了什么以及为何测试”的可测性账本。图模型让结构清晰可审,转换测试让逻辑明确无误,分支抽样将精力集中在有价值的变量上,负向断言捕获状态泄露,而人工测试则评估叙事表现。随着路径不断增多,这些手段相辅相成,既提供了有效的覆盖,又对未测试的部分保持了清晰的边界认知。

相关阅读

继续探索这个主题