6.3 KiB
剧情界面与路线系统重构方案
状态:已确认,待实施
更新日期:2026-07-20
适用范围:ichni Official。本方案不涉及IchniCreatorStudio。
1. 目标与原则
本次重构将剧情页面升级为以叙事时间推进的可拖动画面:左侧 Helper、顶部 Timeline、中心剧情树、右下章节指示器共同呈现章节进度。
剧情路线的排版是叙事与美术设计的一部分,因此必须由每章的 StoryData 静态定义;运行时仅负责生成视图、推导状态、播放动效和筛选可见信息,绝不进行自动图布局或重排。
2. 静态布局与运行时行为
2.1 StoryData 静态定义
每章 StoryData 预先保存:
- 全部 Block、连接关系、
gridColumn与gridRow; - TextBlock 的
Important/Secondary视觉分类; - Block 的解锁条件与变量驱动的互斥路线条件;
- Timeline Marker 的锚点、文本和主线进度;
全局 Helper 不属于任何章节的 StoryData。它由独立的 StoryHelperData 资产保存,
并由 StoryManager 统一引用;这样所有章节共享同一个 Helper 与对话池,后续只需在该资产中维护一次。
gridColumn 表示叙事时间,向右递增;gridRow 表示路线。主线围绕 gridRow = 0 排布,分支向上或向下展开。Important TextBlock 承担主线转折与章节 checkpoint,Secondary TextBlock 用于补充剧情和支线,可使用小数列位置。
只有叙事真正汇合时才连接到同一个后续 Block。两个结局固定在最右侧的结局区,上下分置。
2.2 运行时动态生成
StoryTreeController 根据静态蓝图动态实例化 Block、Connector 和 Timeline Marker View。路线改变时不会移动或重新排列任何节点,只更新各节点状态、连接线视觉和 Timeline 可见性。
3. Block 状态与互斥路线
现有状态扩展为:
| 状态 | 含义 |
|---|---|
Locked |
当前不可用,但后续仍可能解锁。 |
Current |
当前可进入。 |
Completed |
已完成。 |
Forbidden |
已被互斥路线排除,在本章当前路线下不能再进入。 |
每个 Block 同时拥有 unlockCondition 与 forbiddenCondition,二者均使用通用的 StoryCondition 条件树。unlockCondition 留空表示可解锁;forbiddenCondition 留空表示不会被条件禁用。运行时若 forbiddenCondition 先满足,则 Block 进入 Forbidden,优先于 Completed / Current / Locked。
路线使用普通剧情变量配置:例如 chapter0_route_main = 1 表示上方路线、= 2 表示下方路线。上方 Block 可将 unlockCondition 设为 chapter0_route_main == 1,并在 forbiddenCondition 中设为 chapter0_route_main == 2;下方 Block 使用相反配置。这样路线选择、教程、Yarn 条件与其它剧情判断完全共用同一种条件语法。
Forbidden Block 保留在剧情树中、不响应点击,并通过预留的视觉函数显示专用图片或文本。关联 Connector 可同步使用低透明度或失效视觉。Timeline 不显示 Forbidden 路线的 Marker。
4. Timeline
Timeline 表达章节内的叙事时间,而非章节列表。
每个 Marker 单独配置:
markerId;anchorBlockId:唯一的位置来源;- 本地化时间文本或特殊自定义文本;
progressValue:0 至 1 的章节主线进度;- 可选路线条件。
运行时直接读取目标 Block 的 gridColumn 计算 Marker 横坐标。Timeline 固定在屏幕顶部,并随剧情树横向拖动同步移动;纵向拖动不影响 Timeline。
Marker 锚定的 TextBlock 为 Current 或 Completed 时显示;处于 Locked 或 Forbidden 时隐藏。章节进度只取所有已完成、有效 Marker 中最大的 progressValue;两条不同结局都设置为 1.0,支线不参与主线百分比计算。
5. Helper
Helper 使用独立的场景内 HelperTalk 面板,不使用模态 MessageUIPage。
StoryHelperData 是独立的全局 ScriptableObject。每条候选对话可包含本地化文本、剧情/路线条件和权重。当前版本从所有条件满足的候选中随机抽取,并在候选数量大于一时避免连续重复;无可用候选时使用默认兜底对话。
未来可在不改变 UI 架构的前提下,按剧情变量、时间阶段、路线、角色状态等扩展筛选规则。
6. SongBlock
- 点击 SongBlock 后进入选曲页面,并优先选中其配置的目标歌曲;
- 仅进入选曲页面或直接返回,不完成 SongBlock;
- 玩家确认进入目标歌曲时,立刻完成该 SongBlock;之后中途退出游戏不回滚;
- 改选其他歌曲进入游戏,不完成原 SongBlock;
- 返回选曲或剧情时保留来源上下文,回到剧情页面后恢复章节、焦点 Block 与剧情树视口位置。
7. Important TextBlock 与章节 checkpoint
每个 Important TextBlock 都可作为本章重开点。系统为其保存“进入该 Block 之前”的章节快照:
checkpointBlockId;- 已完成 Block 集合;
- 本章剧情变量;
- 本章选项与路线变量。
点击已完成的 Important TextBlock 时,提供“回顾剧情 / 从此处重新开始 / 取消”。选择重开会用 checkpoint 覆盖当前章节的剧情状态、将该 Block 恢复为 Current、重建剧情树并从该 Yarn Node 开始。
重开只改变本章的剧情相关数据;不会回滚歌曲成绩、设置、永久内容解锁 Key 或其他章节的进度。
8. 章节独立性
剧情变量、选项、路线和 checkpoint 都必须按章节保存与读取。Chapter 0 的剧情选择或重开不会影响 Chapter 1。
歌曲成绩、Settings 和永久内容解锁属于全局系统,不纳入章节 checkpoint 的回滚范围。
9. 实施顺序
- 重构 StoryData 与章节级剧情存档的数据契约。
- 增加
Forbidden状态、通用StoryCondition与 Block 视觉接口。 - 移除 Block 基类的固定尺寸覆盖,改由 Prefab/Visual Preset 决定尺寸。
- 实现 Timeline Marker、横向同步和主线进度计算。
- 实现 SongBlock 到选曲、GameScene、剧情页面的完整返回上下文。
- 实现 Helper 对话池。
- 实现 Important TextBlock checkpoint 与章节重开流程。
- 配置 Chapter 0 的真实布局、时间点和两条结局。
- 完成 PC、Android、iOS 的路线、重开、拖动、Safe Area 和存档回归测试。