剧情+对话完善
This commit is contained in:
533
docs/story-programmer-integration-guide.md
Normal file
533
docs/story-programmer-integration-guide.md
Normal file
@@ -0,0 +1,533 @@
|
||||
# ichni Official 剧情系统整合、配置与测试手册
|
||||
|
||||
> 适用对象:程序员、Technical Designer、负责 Unity 配置和剧情 QA 的成员
|
||||
> 适用项目:`ichni Official`
|
||||
> 当前实现:Yarn Spinner `3.2.1`、Unity Localization、ES3、DOTween
|
||||
> 最后更新:2026-07-21
|
||||
|
||||
本文说明如何把剧本编写者交付的 Yarn Scripts 整合进游戏,并配置 StoryData、角色、Timeline、Helper、存档和测试流程。CreatorStudio 不参与本套任务;只有未来任务明确触及节奏游戏元素、共享序列化结构或 Creator 导入流程时,才需要重新评估跨项目同步。
|
||||
|
||||
## 1. 系统边界与数据流
|
||||
|
||||
```text
|
||||
StoryData(静态剧情图、条件、Marker、默认变量)
|
||||
-> StoryTreeController(生成 Block、推导状态、处理回滚)
|
||||
-> TextBlockView -> StoryDialogueController -> DialogueRunner
|
||||
-> VNDialoguePresenter / VNPortraitStage / DialogUIPage
|
||||
-> StoryProgress -> StorySaveModule -> ES3
|
||||
-> SongBlockView -> SongSaves.isTried
|
||||
-> TutorialBlockView -> TutorialFlowController
|
||||
-> StoryTimelineController(Marker 投影、进度、回滚入口)
|
||||
-> StoryHelperController(全局 HelperData、条件对话池)
|
||||
```
|
||||
|
||||
三套持久化数据必须保持隔离:
|
||||
|
||||
| 数据域 | 主要内容 | 回滚本章时是否变化 |
|
||||
|---|---|---|
|
||||
| `SongSaveModule` | `isTried`、`isCompleted`、Accuracy、MaxCombo、FC/AP、Chart Revision | 否 |
|
||||
| `StorySaveModule` | Completed Blocks、章节变量、选项、Marker 快照 | 是,仅当前章节 |
|
||||
| `UnlockSaveModule` | Offline 内容 Key | 否 |
|
||||
|
||||
## 2. 主要代码和资产
|
||||
|
||||
| 路径 | 职责 |
|
||||
|---|---|
|
||||
| `Assets/Scripts/NewStorySystem/Data/StoryData.cs` | 运行时章节数据与查询 |
|
||||
| `Assets/Scripts/NewStorySystem/Data/StoryData.Editor.cs` | StoryData Validation 与 Inspector Preview |
|
||||
| `Assets/Scripts/NewStorySystem/Data/StoryBlockDefinition.cs` | Block 类型、布局、条件和类型专属字段 |
|
||||
| `Assets/Scripts/NewStorySystem/Data/StoryConditionNode.cs` | AND / OR / NOT / Variable / BlockCompleted 条件树 |
|
||||
| `Assets/Scripts/NewStorySystem/Tree/StoryTreeController.cs` | 生成、状态推导、连接、完成、回滚 |
|
||||
| `Assets/Scripts/NewStorySystem/Dialogue/StoryDialogueController.cs` | TextBlock 对话事务与 Yarn Project 切换 |
|
||||
| `Assets/Scripts/NewStorySystem/Dialogue/VNDialoguePresenter.cs` | 台词、选项、快进、记录 |
|
||||
| `Assets/Scripts/NewStorySystem/Dialogue/VNPortraitStage.cs` | 动态立绘实例和动画入口 |
|
||||
| `Assets/Scripts/NewStorySystem/Save/StorySaveModule.cs` | 按章节 ES3 存档与事务 |
|
||||
| `Assets/Scripts/NewStorySystem/Timeline/StoryTimelineController.cs` | Marker、刻度同步、进度和确认回滚 |
|
||||
| `Assets/Scripts/NewStorySystem/Helper/StoryHelperController.cs` | 全局 Helper、加权随机台词和气泡 |
|
||||
| `Assets/Scripts/NewStorySystem/YarnFunctions/` | 项目专有 Yarn Commands / Functions |
|
||||
| `Assets/Story/Chapter0/` | Chapter 0 StoryData、Yarn Project、Yarn Scripts、CharacterRegistry |
|
||||
| `Assets/Localization/Story/` | 当前 Yarn 台词 Unity String Table Collection |
|
||||
|
||||
## 3. 新章节整合流程
|
||||
|
||||
### 3.1 确定稳定 Chapter Index
|
||||
|
||||
`ChapterSelectionUnit.chapterIndex`、`StoryData.chapterIndex`、`StoryManager.storyDatas` 的 Dictionary Key 必须完全一致,包括大小写。
|
||||
|
||||
当前 Chapter 0 使用:
|
||||
|
||||
```text
|
||||
Chapter0
|
||||
```
|
||||
|
||||
`StoryTreeController.BuildChapter` 会在运行时报告三者不一致,但不会擅自改写资产。
|
||||
|
||||
### 3.2 创建章节目录和 Yarn Project
|
||||
|
||||
建议结构:
|
||||
|
||||
```text
|
||||
Assets/Story/Chapter1/
|
||||
Chapter1.yarnproject
|
||||
StoryData_Chapter1.asset
|
||||
CharacterRegistry.asset(也可改为全局 Registry,需统一引用)
|
||||
C1_Intro.yarn
|
||||
C1_Checkpoint.yarn
|
||||
...
|
||||
```
|
||||
|
||||
Yarn Project 的 `Source Yarn Scripts` 建议使用 `**/*.yarn`,并确保不会把其它章节目录意外包含进来。Node 名必须在该 Project 内唯一。
|
||||
|
||||
### 3.3 创建 StoryData
|
||||
|
||||
使用:
|
||||
|
||||
```text
|
||||
Create > Ichni > Story > New > StoryData
|
||||
```
|
||||
|
||||
配置:
|
||||
|
||||
1. `Chapter Index`:与章节资产完全一致。
|
||||
2. `Yarn Project`:拖入本章节 Yarn Project。
|
||||
3. `Initial Variables`:登记章节变量的默认值和类型。
|
||||
4. `Blocks`:配置完整静态剧情图。
|
||||
5. `Timeline Markers`:配置重要时间点。
|
||||
6. `Exclusive Route Groups`:只用于 Validation,登记互斥终点组。
|
||||
|
||||
最后在场景 `StoryManager.storyDatas` 中添加:
|
||||
|
||||
```text
|
||||
Key: Chapter1
|
||||
Value: StoryData_Chapter1
|
||||
```
|
||||
|
||||
## 4. Initial Variables
|
||||
|
||||
每个变量定义包含:
|
||||
|
||||
- `Key`
|
||||
- `Type`:Bool / Int / Float / String
|
||||
- 对应类型的 `Default`
|
||||
|
||||
默认值不写入玩家存档。只有 Yarn 或其它剧情入口第一次写入同名变量时,才产生存档覆盖值。`remove_variable` 会删除覆盖值,使读取重新回到 StoryData 默认值。
|
||||
|
||||
建议所有 Yarn 会读写的变量都在 `Initial Variables` 登记,即使运行时允许首次写入未声明变量。这样能让策划、程序员和 Validation 审阅时看到章节完整变量表。
|
||||
|
||||
## 5. Block 通用配置
|
||||
|
||||
### 5.1 Identity 与 Layout
|
||||
|
||||
- `ID`:稳定唯一,连接、存档、选项和 Marker 都依赖它。
|
||||
- `Type`:Text / Song / Tutorial。
|
||||
- `Column`:叙事时间向右推进;列坐标代表 Block 中心点。
|
||||
- `Row`:路线位置,正数向下、负数向上。
|
||||
|
||||
运行时默认步距:
|
||||
|
||||
- `columnStep = 720`
|
||||
- `rowStep = 525`
|
||||
- `helperReservedLeftSpace = 400`
|
||||
|
||||
Prefab 自己决定尺寸,控制器不覆盖 `sizeDelta`:
|
||||
|
||||
| Block | 当前设计尺寸 |
|
||||
|---|---|
|
||||
| Important Text | `600 x 375` |
|
||||
| Secondary Text | `400 x 200` |
|
||||
| Song | `400 x 100` |
|
||||
| Tutorial | `400 x 100` |
|
||||
|
||||
如果未来修改 Prefab 尺寸,还要同步 `StoryData.Editor.cs` 中的 Preview 尺寸常量。
|
||||
|
||||
### 5.2 Next Blocks 与 Connected Rule
|
||||
|
||||
`Next Blocks` 同时承担:
|
||||
|
||||
- 运行时连接线。
|
||||
- 目标 Block 的自动前置条件来源。
|
||||
|
||||
目标 Block 的 `Connected Rule`:
|
||||
|
||||
| 规则 | 语义 |
|
||||
|---|---|
|
||||
| `Require All Direct Predecessors` | 所有直接前置完成后可用;默认值 |
|
||||
| `Require Any Direct Predecessor` | 任一直接前置完成即可;用于互斥分支汇合 |
|
||||
| `Ignore Connections` | 连线只作视觉用途,不参与解锁 |
|
||||
|
||||
自动连接条件与手写 `Unlock Condition` 按 AND 合并。没有前置连接的入口 Block 不受自动条件限制。
|
||||
|
||||
### 5.3 Unlock 与 Forbidden
|
||||
|
||||
两者共用 `StoryCondition`:
|
||||
|
||||
- `All Of (AND)`
|
||||
- `Any Of (OR)`
|
||||
- `Not`
|
||||
- `Block Completed`
|
||||
- `Variable Compare`
|
||||
|
||||
状态优先级:
|
||||
|
||||
```text
|
||||
Forbidden > Completed > Current > Locked
|
||||
```
|
||||
|
||||
互斥路线应同时配置 Unlock 和 Forbidden。例如:
|
||||
|
||||
```text
|
||||
Route A Unlock: c0_signal_route == 1
|
||||
Route A Forbidden: c0_signal_route == 2
|
||||
|
||||
Route B Unlock: c0_signal_route == 2
|
||||
Route B Forbidden: c0_signal_route == 1
|
||||
```
|
||||
|
||||
不要为相同语义再增加一套 Route Binding 字段;运行时路线始终以通用条件树为准。
|
||||
|
||||
## 6. TextBlock 配置
|
||||
|
||||
字段:
|
||||
|
||||
- `Yarn Node`:点击时启动的入口 Node。
|
||||
- `Title Key`:Block 标题的 Unity Localization Entry Key。
|
||||
- `Importance`:Important / Secondary。
|
||||
|
||||
当前限制:`TextBlockView` 仍直接把 `titleKey` 字符串显示到 TMP,没有解析 Unity Localization。这是发布前本地化待办;配置时仍应从现在开始填写正式 Key,避免后续迁移时重新清点内容。
|
||||
|
||||
TextBlock 运行流程:
|
||||
|
||||
1. `StoryDialogueController` 检查 Runner、章节上下文和 Yarn Node 是否存在。
|
||||
2. 复制 `ChapterStorySave` 并开始事务。
|
||||
3. `StoryProgress.BeginBlockMutation` 捕获同列 Marker 快照。
|
||||
4. Yarn 运行,选项和变量只修改内存。
|
||||
5. 正常结束:完成 Block、提交 ES3、执行排队的解锁/Message。
|
||||
6. Back 或启动失败:恢复进入前快照并刷新现有 StoryTree。
|
||||
|
||||
## 7. SongBlock 配置
|
||||
|
||||
字段:
|
||||
|
||||
- `Song ID`:必须等于目标 `SongItemData.songName`,不能使用 `displaySongName`。
|
||||
- `Illustration Y`:范围 `-74.25` 到 `74.25`。
|
||||
|
||||
插画和曲名资料由 `ChapterSelectionUnit` 中的 `SongItemData` 提供,不在 StoryData 重复维护。
|
||||
|
||||
完成规则:
|
||||
|
||||
- 玩家确认进入目标歌曲时,`InformationTransistor.PrepareGameLaunch` 调用 `SongSaveModule.MarkSongTried`。
|
||||
- `SongStatusSave.isTried = true` 是 SongBlock 的唯一持久化完成事实。
|
||||
- 即使玩家进入后中途退出,也算尝试并完成对应 SongBlock。
|
||||
- Timeline 回滚不会把 `isTried` 改回 false;重新构建剧情树会再次把该 SongBlock 同步为完成。
|
||||
|
||||
同时仍要通过 `UnlockSaveModule.CanEnterSong` 检查章节和歌曲授权,SongBlock 不能绕过普通选曲的锁定规则。
|
||||
|
||||
## 8. TutorialBlock 配置
|
||||
|
||||
字段:
|
||||
|
||||
- `Display Name`
|
||||
- `Tutorial Key`:`TutorialCollection` 的稳定 Key。
|
||||
- `Progress Variable`:玩家选择游玩或跳过后写入 `true` 的章节变量。
|
||||
- `Difficulty Save ID`:目标 `DifficultyData.saveDifficultyId`,不是列表下标。
|
||||
|
||||
玩家每次点击 Completed TutorialBlock 都可以重新选择游玩或跳过。第一次选择任一项时会立刻完成 TutorialBlock 并解锁后续;游玩教程不等待结算。
|
||||
|
||||
当前 `TutorialFlowController` 的“游玩教程/跳过教程”文本仍是硬编码中文,发布前需要迁移到 Unity Localization。
|
||||
|
||||
## 9. Timeline Marker
|
||||
|
||||
每个 Marker 配置:
|
||||
|
||||
- `Marker ID`:章节内唯一。
|
||||
- `Anchor`:必须是 TextBlock ID。
|
||||
- `Label Key`:时间或特殊叙事文本的 Unity Localization Key。
|
||||
- `Main Progress`:是否参与主线百分比。
|
||||
- `Value`:完成 Anchor 后贡献的 `0..1` 进度;互斥结局都可以是 `1`。
|
||||
|
||||
显示规则:
|
||||
|
||||
- Anchor 为 `Current` 或 `Completed`:显示。
|
||||
- Anchor 为 `Locked` 或 `Forbidden`:隐藏。
|
||||
|
||||
位置直接读取 Anchor TextBlock 的实际视觉中心,并监听 Story ScrollRect;装饰刻度使用一张 `Image Type = Tiled` 的 Repeat Image 跟随同一横向位移。
|
||||
|
||||
点击 Marker 只有在对应“列之前快照”已经创建后才可交互。确认回滚会重置目标列及右侧的 Block、选项和章节变量,并删除失效的后续 Marker 快照。
|
||||
|
||||
当前 Timeline 回滚确认框仍有硬编码中文;发布前需要迁移到 Unity Localization。
|
||||
|
||||
## 10. Exclusive Route Groups
|
||||
|
||||
该列表只用于编辑器 Validation,不参与 Runtime。
|
||||
|
||||
一个 Group 应包含同一章节中互斥的两个或多个终点 Block。Validation 会检查:
|
||||
|
||||
- Group ID 是否有效和重复。
|
||||
- 终点 Block 是否存在和重复。
|
||||
- 终点是否仍有 Next Block。
|
||||
- 互斥终点是否配置了 Forbidden Condition。
|
||||
|
||||
通用条件树可以表达任意复杂条件,Validation 无法数学证明两条路线真正互斥,最终仍需人工测试。
|
||||
|
||||
## 11. Yarn 与 Unity Localization
|
||||
|
||||
所有新剧情文本只使用 Unity Localization。
|
||||
|
||||
### 11.1 Yarn Project Inspector
|
||||
|
||||
选中 `.yarnproject` 后检查:
|
||||
|
||||
1. `Source Yarn Scripts` 覆盖正确目录。
|
||||
2. `Base Language` 与 Yarn 源文本语言一致。
|
||||
3. 开启 `Use Unity Localisation System`。
|
||||
4. `String Table Collection` 指向目标 Unity String Table Collection。
|
||||
5. 点击 `Add Line Tags to Yarn Scripts`,为缺少 ID 的台词和选项生成 `#line:`。
|
||||
6. 保存并重新导入,确认 Yarn Project 没有编译错误。
|
||||
|
||||
当前 Chapter 0 使用 `Chapter0_Lines`,而 `StoryDialogueController` 已预留统一 `yarnLinesTable`。在 Chapter 1 大量接入前,推荐把各章节 Yarn 台词统一到一个 `YarnLines` String Table Collection;这样场景中的单个 `UnityLocalisedLineProvider` 在切换 Yarn Project 时无需同时切换表。
|
||||
|
||||
若暂时保留 `Chapter0_Lines`:
|
||||
|
||||
- `UnityLocalisedLineProvider.stringsTable` 必须指向 `Chapter0_Lines`。
|
||||
- `StoryDialogueController.yarnLinesTable` 留空时不会覆盖现有 Provider 配置。
|
||||
|
||||
### 11.2 Locale
|
||||
|
||||
首发至少验证:
|
||||
|
||||
- English:`en`
|
||||
- Simplified Chinese:`zh-CN`
|
||||
- Japanese:`ja`
|
||||
- Korean:`ko`
|
||||
- Vietnamese:`vi-VN`
|
||||
|
||||
新增 Yarn 行后,确认五张 String Table 都有同一 Line ID。不要通过删除并重新生成 Line Tag 的方式“整理”ID,否则会同时影响本地化和已保存选项。
|
||||
|
||||
### 11.3 非 Yarn 文本
|
||||
|
||||
建议按用途拆表:
|
||||
|
||||
| 内容 | 建议 String Table |
|
||||
|---|---|
|
||||
| Yarn 台词和选项 | `YarnLines` |
|
||||
| TextBlock 标题、Timeline、章节标题 | `StoryUI` |
|
||||
| Helper 名称和气泡 | `StoryHelper` |
|
||||
| MessageBox / SelectionBox | `Message` |
|
||||
|
||||
当前场景中 `StoryTimelineController.localizationTable` 和 `StoryHelperData.localizationTable` 仍为空;完成正式文本接入时必须补齐。
|
||||
|
||||
## 12. 角色与立绘配置
|
||||
|
||||
### 12.1 CharacterData
|
||||
|
||||
创建:
|
||||
|
||||
```text
|
||||
Create > Ichni > Story > New > CharacterData
|
||||
```
|
||||
|
||||
字段:
|
||||
|
||||
- `Character ID`:与 Yarn 的 `CharacterName` 完全一致,例如 `Asahi`。
|
||||
- `Display Name Key`:角色显示名的 Unity Localization Key。
|
||||
- `Portrait Style`:Sprite / Live2D / Spine。
|
||||
- `Position Offset`:归一化舞台偏移。
|
||||
- `Emotion Sprites`:`normal`、`happy`、`angry` 等表情到 Sprite 的映射。
|
||||
- `Dynamic Portrait Prefab`:未来 Live2D / Spine 使用,必须实现 `IPortraitRenderer`。
|
||||
|
||||
把 CharacterData 登记到 `CharacterRegistry.characters`,再把 Registry 赋给场景 `StoryManager.characterRegistry`。
|
||||
|
||||
当前限制:`VNDialoguePresenter` 的 Speaker TMP 仍直接显示 Yarn 的 `CharacterName`,尚未通过 `CharacterData.displayNameKey` 本地化。该字段先按规范配置,发布前应补上显示名解析。
|
||||
|
||||
### 12.2 VNPortraitStage
|
||||
|
||||
场景需配置:
|
||||
|
||||
- `_spritePortraitPrefab`
|
||||
- `_portraitContainer`
|
||||
|
||||
Sprite Prefab 必须包含 `SpritePortraitRenderer`;Live2D / Spine Prefab 必须有实现 `IPortraitRenderer` 的组件。
|
||||
|
||||
当前舞台按需 Instantiate,`hide_portrait` 时 Destroy。对话数量增大后若发现频繁分配,应再评估池化;现在不要为了未知规模提前重构。
|
||||
|
||||
## 13. Dialog 场景装配
|
||||
|
||||
`StoryDialogueRoot` 应包含:
|
||||
|
||||
- `DialogueRunner`
|
||||
- `UnityLocalisedLineProvider`
|
||||
- `VNDialoguePresenter`
|
||||
- `StoryDialogueController`
|
||||
|
||||
`StoryDialogueController`:
|
||||
|
||||
- `dialogueRunner`
|
||||
- `storyUIPage`
|
||||
- 可选的统一 `yarnLinesTable`
|
||||
|
||||
`DialogUIPage`:
|
||||
|
||||
- `portraitStage`
|
||||
- `dialogueText`
|
||||
- `speakerContainer` / `speakerText`
|
||||
- `advanceButton`
|
||||
- `fastForwardButton`
|
||||
- `backButton`
|
||||
- `showHistoryButton`
|
||||
- `dialogueHistoryPage`
|
||||
- `choiceFrame`
|
||||
- `choiceButtons`
|
||||
|
||||
`DialogueHistoryPage` 必须有全屏可接收 Raycast 的覆盖层;打开时要阻断底层 Dialog 输入。
|
||||
|
||||
当前 `MenuScene` 仍启用了调试用 `ConsoleLinePresenter`。它会额外把每行本地化结果输出到 Console;发布构建前应从 DialogueRunner Presenter 列表移除或禁用,只保留 `VNDialoguePresenter`。
|
||||
|
||||
## 14. Helper 配置
|
||||
|
||||
Helper 使用全局 `StoryHelperData`,不属于单个 StoryData。
|
||||
|
||||
字段:
|
||||
|
||||
- `Helper ID`
|
||||
- `Portrait Sprite`
|
||||
- `Localization Table`
|
||||
- `Display Name Key`
|
||||
- `Fallback Dialogue Key`
|
||||
- `Dialogue Pool`
|
||||
|
||||
每条候选包含:
|
||||
|
||||
- `ID`
|
||||
- `Text Key`
|
||||
- `Availability`:复用 StoryCondition;留空时始终可用。
|
||||
- `Weight`
|
||||
|
||||
运行时会从满足条件的候选中加权随机抽取,并尽量避免连续重复。没有候选时使用 Fallback。`StoryHelperController` 会动态实例化独立 `HelperTalk` Prefab,不使用 MessageBox。
|
||||
|
||||
当前 `Assets/Story/StoryHelperData.asset` 的 Localization Table 为空且 Dialogue Pool 为空,只有 Fallback Key;正式 Helper 文本测试前需要配置对应 String Table 和至少一条候选。
|
||||
|
||||
## 15. StoryData Validation
|
||||
|
||||
在 StoryData Inspector 点击 `Validate Story Data`。Console 现在会输出:
|
||||
|
||||
- 一条摘要。
|
||||
- 每个问题一条独立 Warning 或 Error。
|
||||
|
||||
不要再把整份报告拼到同一条多行日志;Unity Console 折叠行不会按内嵌换行扩展高度,会造成文字重叠。
|
||||
|
||||
当前 Validation 检查:
|
||||
|
||||
- Chapter Index 和 Yarn Project。
|
||||
- Initial Variable Key 的格式和重复。
|
||||
- Block ID 重复、Next Block 引用、类型必要字段。
|
||||
- Yarn Node 是否存在及是否被多个 TextBlock 共用。
|
||||
- 入口、不可达 Block、环路、非向前连接和终点。
|
||||
- Unlock / Forbidden 条件树的空节点和无效 Block 引用。
|
||||
- Timeline Marker ID、Anchor、Label 和重复 Anchor。
|
||||
- Exclusive Route Groups。
|
||||
- Yarn 文件中的 `<<declare>>` 和 `<<set $...>>` 旧语法。
|
||||
|
||||
Validation 不检查:
|
||||
|
||||
- Scene / Prefab 引用是否齐全。
|
||||
- Song ID 是否真的存在于 ChapterSelectionUnit。
|
||||
- TutorialCollection 内容。
|
||||
- Unity Localization Entry 是否齐全。
|
||||
- 互斥条件是否在逻辑上百分之百正确。
|
||||
- 所有语言的排版和溢出。
|
||||
|
||||
因此 Validation 通过不等于剧情已经达到发布质量。
|
||||
|
||||
## 16. 当前 Chapter 0 的已知配置状态
|
||||
|
||||
审阅时确认:
|
||||
|
||||
- `StoryData_Chapter0.chapterIndex` 已修正为 `Chapter0`,与 ChapterSelectionUnit 和 StoryManager Key 对齐。
|
||||
- `Chapter0.yarnproject` 的 Base Language 是 `en`,但旧 `C0_A0.yarn` 含中文原文;正式生产前应确定基础语言并统一。
|
||||
- `C0_A0.yarn` 仍包含废弃的 `declare / set $` 示例,Validation 会逐条报告;此前已经明确该旧台本不作为新系统规范。
|
||||
- 五份 `C0_RollbackDemo_*.yarn` 是当前永久变量、选项记忆和 Timeline 回滚的测试样例。
|
||||
- `StoryTimelineController.localizationTable`、`StoryHelperData.localizationTable` 尚未配置。
|
||||
- TextBlock 标题、Speaker 显示名、Tutorial 选择和 Timeline 回滚确认仍有待完成 Unity Localization 接入。
|
||||
|
||||
## 17. 推荐测试顺序
|
||||
|
||||
### 17.1 静态检查
|
||||
|
||||
1. Yarn Project 无编译错误。
|
||||
2. StoryData Validation 没有 Error。
|
||||
3. 所有 Warning 已确认是临时内容还是需要修复。
|
||||
4. StoryData Preview 中 Block 尺寸、中心列和连线符合预期。
|
||||
|
||||
### 17.2 新档主流程
|
||||
|
||||
1. 清除当前章节 StorySave。
|
||||
2. 打开章节,确认只有入口 Block 为 Current。
|
||||
3. 完成 TextBlock,确认后继解锁并在重启后保持。
|
||||
4. 在重要选择中选择 Route A,确认 Route B 变为 Forbidden。
|
||||
5. 再次进入已完成 TextBlock,确认选项自动采用。
|
||||
|
||||
### 17.3 对话按钮
|
||||
|
||||
1. `Advance` 第一次补全文字、第二次下一句。
|
||||
2. `FastForward` 只影响当前一次 Dialog。
|
||||
3. FastForward 可跨过已记忆选项,但不会越过首次选择页面。
|
||||
4. `History` 只显示当前一次对话,能滚动并阻断底层输入。
|
||||
5. `Back` 中途退出后,变量、选项、Block 完成状态全部恢复。
|
||||
|
||||
### 17.4 Timeline
|
||||
|
||||
1. Marker 只在 Anchor Current / Completed 时显示。
|
||||
2. 横向拖动 StoryTree,Marker 和 Repeat Tick 同步移动。
|
||||
3. 完成 Marker 所在列后按钮可点击。
|
||||
4. 回滚后目标列及右侧重新开放,目标列之前保持不变。
|
||||
5. Song 成绩、`isTried`、Unlock Key、Settings 和其它章节不变。
|
||||
|
||||
### 17.5 Song 与 Tutorial
|
||||
|
||||
1. SongBlock 自动选中目标歌曲。
|
||||
2. 只浏览选曲再返回,不写 `isTried`。
|
||||
3. 确认进入目标歌曲后,即使中途退出,SongBlock 仍完成。
|
||||
4. Tutorial 选择游玩或跳过都完成 Block。
|
||||
5. Completed Tutorial 仍可再次点击回顾。
|
||||
|
||||
### 17.6 本地化
|
||||
|
||||
逐一切换 `en`、`zh-CN`、`ja`、`ko`、`vi-VN`:
|
||||
|
||||
1. Yarn 台词与选项正确。
|
||||
2. Character 名称正确。
|
||||
3. TextBlock 标题正确。
|
||||
4. Timeline 文本和回滚确认正确。
|
||||
5. Helper 名称与气泡正确。
|
||||
6. MessageBox / SelectionBox 正确。
|
||||
7. 长文本不溢出,CJK 与越南语字体包含所需字形。
|
||||
|
||||
## 18. 常见故障定位
|
||||
|
||||
| 现象 | 检查顺序 |
|
||||
|---|---|
|
||||
| 点击 TextBlock 无反应 | Block State -> Button -> StoryDialogueController -> Yarn Node -> Yarn Project |
|
||||
| Yarn Node 不存在 | StoryData 的 Node 名、Yarn Project source glob、编译诊断 |
|
||||
| 对话退出后变量仍存在 | 是否使用项目 `set_*`;全局副作用是否经过 Commit Queue |
|
||||
| 选项被意外跳过 | Option Line ID 是否沿用;是否已有 Choice Record;是否错误修改选项组 |
|
||||
| Marker 不移动 | Story ScrollRect 引用、Marker Container 坐标转换、Anchor View 是否存在 |
|
||||
| SongBlock 不完成 | `PrepareGameLaunch` 是否调用、Song ID 是否匹配、`SongStatusSave.isTried` |
|
||||
| SongBlock 错误完成 | 是否有多个章节/歌曲复用了同一个 `songName`;该字段必须全局稳定 |
|
||||
| Helper 只显示 Key | StoryHelperData Localization Table 或 Entry 缺失 |
|
||||
| Speaker 显示内部 ID | 当前显示名本地化尚未接入,不能只配置 displayNameKey 就视为完成 |
|
||||
| Console 出现多份台词日志 | 调试用 ConsoleLinePresenter 仍启用 |
|
||||
|
||||
## 19. 发布前剧情系统 Gate
|
||||
|
||||
满足以下条件后,剧情和对话系统才可进入 Release 验收:
|
||||
|
||||
1. Chapter 0 所有正式 Yarn 台本不再使用废弃临时变量语法。
|
||||
2. Yarn Base Language 与源文本一致。
|
||||
3. 五种首发语言的 Yarn、Story UI、Helper、Message 文本齐全。
|
||||
4. TextBlock 标题、Speaker、Tutorial、Timeline 确认框全部完成 Unity Localization。
|
||||
5. ConsoleLinePresenter 从发布配置移除。
|
||||
6. StoryData Validation 无 Error,所有 Warning 有明确处理结论。
|
||||
7. 两个互斥结局、支线 Forbidden、选项记忆和 Timeline 回滚完成回归测试。
|
||||
8. SongBlock `isTried`、Tutorial 回顾、Back 回滚、FastForward 会话边界均通过测试。
|
||||
9. Android、iOS、PC 分别完成长文本、输入和场景往返测试。
|
||||
10. 正式发布前冻结 Story Save v1;发布后结构变化必须编写迁移,不能继续直接删档。
|
||||
Reference in New Issue
Block a user