Files
ichni_Official/docs/tutorial-block-system.md

101 lines
6.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# TutorialBlock 教程流程与 Chapter 0 配置
## 规则
TutorialBlock 点击后通过通用 `SelectionBox` 动态生成“游玩教程 / 跳过教程”两个选项。玩家选择任一选项的瞬间,系统都会:
1. 将 TutorialBlock 的 `tutorialProgressVariable` 写为 `true`
2. 保存全局剧情变量。
3. 将该 TutorialBlock 标记为 Completed用于故事树的节点外观和防止重复点击。
4. 重新计算所有 StoryBlock 的 `UnlockCondition`
后续 Block 必须通过 `VariableCondition` 读取教程变量解锁,不要依赖 TutorialBlock 的完成记录。选择“游玩教程”后会进入 GameScene选择“跳过教程”则留在故事树。教程游玩中退出、失败或关闭游戏不会回退已经确认的解锁状态。
## 运行时职责
| 模块 | 职责 |
|---|---|
| `StoryProgress` | 统一执行“写变量、保存、刷新故事树”;`ResolveTutorial` 同时更新教程节点完成状态。 |
| `TutorialFlowController` | 验证 TutorialBlock 配置,并临时组装教程所需的两个 `SelectionBoxOption`。 |
| `SelectionBoxUIPage` | 通用多选弹窗页面:动态生成一个 `SelectionBox`,阻断底层输入并在选择后销毁该实例。 |
| `SelectionBox` / `SelectionBoxButton` | 动态生成任意数量的选项按钮并确保一次显示只执行一个回调。 |
| `TutorialCollection` | 用 `tutorialKey` 查询教程曲目的 `SongItemData`。 |
| `InformationTransistor` | 用 `MenuReturnDestination` 保存唯一的返回目标,替代旧的两个返回 bool。 |
`MenuReturnDestination.SongSelection` 供普通选曲使用;`MenuReturnDestination.Story` 供教程使用。教程从 GameScene 返回时MenuScene 会显式重建来源章节的 StoryTree。
## Key 命名规则
所有新 Tutorial Key 和剧情变量 Key 只使用小写英文、数字和下划线:
| 用途 | Chapter 0 示例 |
|---|---|
| Tutorial Key | `chapter0_intro` |
| 教程进度变量 | `story_tutorial_chapter0_intro_resolved` |
| TutorialBlock ID建议 | `tutorial_0_intro` |
不要用显示名称、空格、点号或本地化文本作逻辑 Key。`blockId` 是 StoryTree 内部节点标识,旧内容可继续保留既有的 `A-0` 格式;新内容建议使用清晰且稳定的名称。
## 配置 Chapter 0
当前 `Assets/Story/Chapter0/StoryData_Chapter0.asset` 还没有 TutorialBlock需要在 Unity Inspector 中按以下步骤添加。
### 1. 配置教程曲目表
1. 打开 `Assets/Resources/TutorialCollection.asset`
2.`songs` 字典中将现有 Chapter 0 教程条目的 Key 调整为 `chapter0_intro`。保留其对应的 `SongItemData`,不要重新手工复制曲目数据。
3. 检查该教程条目的 `difficultyDataList`:目标难度应为 `isAvailable = true`,并确认它的 `saveDifficultyId`。当前 Chapter 0 Tutorial 的 Easy 难度应使用 ID `0`;以 Inspector 实际显示为准。
### 2. 在 StoryData 新增起始教程节点
1. 打开 `Assets/Story/Chapter0/StoryData_Chapter0.asset`
2.`blocks` 新增一个条目,或按你的章节布局将其放在第一个剧情节点之前:
| 字段 | 建议值 |
|---|---|
| `blockId` | `tutorial_0_intro` |
| `blockType` | `Tutorial` |
| `tutorialName` | 当前阶段可先填临时显示名,例如 `Chapter 0 Tutorial` |
| `tutorialKey` | `chapter0_intro` |
| `tutorialProgressVariable` | `story_tutorial_chapter0_intro_resolved` |
| `tutorialDifficultySaveId` | `0`(以教程曲目的实际 `saveDifficultyId` 为准) |
| `nextBlockIds` | 第一个后续剧情节点,例如 `A-0` |
| `unlockCondition` | 留空,使教程节点在章节开始时可点击 |
3. 为原本的第一个剧情节点 `A-0` 设置 `UnlockCondition`:选择 `VariableCondition`,并填写:
| 字段 | 值 |
|---|---|
| `variableName` | `story_tutorial_chapter0_intro_resolved` |
| `comparison` | `Equal` |
| `value` | `1` |
如果该节点还有其它前置要求,请使用 `AllOfCondition` 将原条件与上述 `VariableCondition` 组合。不要把它改成 `BlockCompletedCondition(tutorial_0_intro)`,否则会失去与 Yarn 和其它剧情变量共用条件系统的优势。
### 3. 配置通用 SelectionBox
TutorialBlock 不再需要专属弹窗。只需配置一套可供其它系统复用的 SelectionBox
1. 创建一个 `SelectionBoxButton` Prefab根节点具有 `Button``SelectionBoxButton`,子节点具有 `TMP_Text`。将 Button 和文本分别赋给 `button``labelText`
2. 创建一个 `SelectionBox` Prefab根节点具有 `CanvasGroup``SelectionBox`;配置标题 `TMP_Text`、可选内容 `TMP_Text`、选项容器 `RectTransform`,并把上一步 Prefab 赋给 `optionButtonPrefab`
3.`Assets/Scenes/MenuScene.unity` 创建一个全屏覆盖页:根节点具有 `CanvasGroup``SelectionBoxUIPage`,初始建议 `alpha = 0``interactable = false``blocksRaycasts = false`
4. 在该覆盖页下创建 `selectionBoxContainer`,并将它赋给 `SelectionBoxUIPage.selectionBoxContainer`;将上一步的 `SelectionBox` Prefab 赋给 `selectionBoxPrefab`
5. 选中 `MenuManager`,把该 `SelectionBoxUIPage` 组件拖入新的 `selectionBoxUIPage` 字段。
教程点击时会运行时生成一个 SelectionBox并生成两个按钮`游玩教程``跳过教程`。未来其它非 Yarn 的交互(例如奖励二选一、离开确认、章节分支)可以传入自己的标题、内容和 `SelectionBoxOption` 列表复用这套 UI。按钮正式本地化留待剧情文本与本地化阶段处理。
## 验证清单
1. 使用新存档或 StoryTree 的 `DebugResetChapterProgress` 重置 Chapter 0该调试重置现在也会清除本章节的教程变量。
2. 进入 Chapter 0确认只有 TutorialBlock 可点击,`A-0` 保持 Locked。
3. 点击 TutorialBlock再点击“跳过教程”节点应变为 Completed`A-0` 应立即成为 Current重进游戏后状态应保留。
4. 重置后选择“游玩教程”:确认进入 Chapter 0 Tutorial 的指定难度,且 `A-0` 在确认按钮点击后已解锁。
5. 在教程暂停页或结算页返回菜单:应回到 Chapter 0 的 StoryPage而不是 SongSelection 页面。
6. 通过普通选曲进入歌曲后返回菜单:应仍回到 SongSelection 页面,且歌曲/难度缓存不受影响。
## 配置错误的表现
以下任一配置缺失时TutorialBlock 会输出警告且不会解锁后续剧情:`tutorialKey``tutorialProgressVariable``tutorialDifficultySaveId`、TutorialCollection 中的曲目、可用的目标难度、`SelectionBoxUIPage` 引用、SelectionBox Prefab 或选项按钮 Prefab。
这是一项运行时保护;本阶段不增加导入器或 Editor 阶段的额外防呆校验。