docs(save): 更新存档规范与 Yarn 节点类型文档

This commit is contained in:
2026-06-24 22:45:32 +08:00
parent b1fdec64e1
commit 009776eb32
3 changed files with 85 additions and 49 deletions
+40 -26
View File
@@ -8,7 +8,6 @@
| --- | --- | --- |
| Yarn 变量 | `Game Loop/YarnVariableStorage.cs` | 运行时 `$` / `$global_` 读写 |
| **本目录** | `SaveSystem/` | 快照结构、捕获/还原、槽位落盘、流程编排 |
| 深度维修(旧) | `DeepRepairDataRegistry.cs` | FixSystem 等 IDataP5 前临时保留 |
| 槽位 / 截图 | `SlotManager` / `SlotThumbnailCapture` | P2 基础版:slot_0 自动档、slot_1..8 手动档、sidecar、缩略图、原子写 |
**不要**再往 `YarnVariableStorage` 上堆存档逻辑。
@@ -19,7 +18,10 @@
// 自动存档(节点进入事件触发)
yield return SaveRestoreOrchestrator.AutoSaveRoutine(nodeName);
// 手动存档:复制最近自动档
// Yarn 显式存档(<<save>>,默认 omit anchor
yield return SaveRestoreOrchestrator.ExplicitSaveRoutine();
// 手动存档:复制最近落盘档(含 OnNodeStart 与 <<save>>
SaveRestoreOrchestrator.CreateManualSlot(slotIndex);
// 槽位读档
@@ -36,6 +38,17 @@ yield return SnapshotService.Restore(snap);
YarnVariableStorage.Instance.SetValue("$foo", 1f);
```
Yarn 脚本:
```yarn
<<save>>
```
- 放在目标节点**末尾**:所有状态命令(`switch_fix_system_to``hide_dialog``play_timeline` 等)执行完毕之后,`<<jump>>` / `<<detour>>` 之前。
- 默认 **omit anchor**`anchor.nodeName` 为空);读档时不重进 Yarn,仅还原 scene + sections + 变量。
- 绕过 tag / `no_save` 的自动判定(`CanExplicitSave`);仍受读档中、暂停、SuppressAutoSave 门控。
-`OnNodeStart` 分工:常规 `hub` / `linear` / `content` 仍靠节点进入自动存;`<<save>>` 用于即将进入无对话 / Fix 交互等 `OnNodeStart` 覆盖不到的边界。
正式槽位路径:`persistentDataPath/AllOurBrokenParts/saves/slot_x/{snapshot.json, meta.json, thumbnail.png}`
P1 测试落盘路径:`persistentDataPath/AllOurBrokenParts/snapshot_test/latest_snapshot.json`(首次访问槽位系统时会尝试迁移到 `slot_0`
@@ -53,8 +66,7 @@ SaveSystem/
├── SnapshotService.cs Capture / Restore 对外 API
├── SnapshotPersistence.cs 文件读写、JSON 序列化、旧档检测
├── SaveRestoreOrchestrator.cs UI + 落盘 + 读盘编排
├── DeepRepairSnapshot.cs 深度维修占位(P5)
├── DeepRepairDataRegistry.cs 旧 IData 容器(P5 前)
├── SaveYarnCommand.cs Yarn <<save>> 显式存档
├── ScreenSnapshotHelper.cs screen section 实现细节
├── SlotTypes.cs P2:槽位常量、sidecar、UI 视图模型
├── SlotFileSystem.cs P2:槽位路径 + 原子写
@@ -69,6 +81,7 @@ SaveSystem/
├── AudioSnapshotProvider.cs order 50
├── TimelineSnapshotProvider.cs order 60
├── FixSnapshotProvider.cs order 65
├── FixPanelSnapshotProvider.cs order 66
└── ScreenSnapshotProvider.cs order 70
```
@@ -137,14 +150,13 @@ Phase 4 P4:淡入淡出等演出时序
| `scene` | 当前场景名(Addressable key),读档时最先加载 |
| `anchor` | 恢复锚点:`sceneSoName` + `yarnProjectId` + `nodeName`;最后阶段加载对话并重进节点 |
| `yarnVariables` | floats / strings / bools |
| `sections` | key 为 `SnapshotProviderIds`,值为各 DTO**表现层状态env / actor / audio / timeline / fix / screen** |
| `deepRepair` | **P5 深度维修**BlockPuzzle / Cutting / AnalysisMode 等)。P1 阶段已预留 `DeepRepairSnapshotDto`,但详细子系统状态暂不捕获;待存档系统主干稳定后再补充并测试 |
| `sections` | key 为 `SnapshotProviderIds`,值为各 DTO;表现层与维修子模块env / actor / fix / bodyModule / blockPuzzle …)统一在此 |
> 宏观信息(场景、章节、节点)直接位于 `SaveSnapshot` 根对象,不再冗余到 `sections`;槽位 / 「继续游戏」UI 需要展示时,从 `scene` / `anchor` 直接读取。
## 新增一个可存子系统(表现层)
## 新增一个可存子系统
表现层子系统通过 Provider 注册到 `sections`
所有可存子系统(含维修小游戏)均通过 Provider 注册到 `sections`,用 `RestoreOrder` 控制同 Phase 内的还原顺序
1.`SaveSnapshot.cs` 增加 DTO 类。
2.`SnapshotRegistry.cs``SnapshotProviderIds` 区域增加稳定 id,并加入 `RequiredForCapture`(若 P1 必须存)。
@@ -157,13 +169,9 @@ Phase 4 P4:淡入淡出等演出时序
> **例外**`scene`(场景加载)与 `anchor`(章节+节点重进)属于**核心叙事坐标**,由 `SnapshotCapture` / `SnapshotRestore` 框架直管,不走 Provider 注册。新增「核心层」字段需修改 `SaveSnapshot` 根对象与对应编排方法。
## Fix 场景快照P1 接口层完成)
## Fix 场景快照
Fix 场景维修场景)的快照存储在 `sections["fix"]`,由 `FixSnapshotProvider`order 65)管理
### 为什么 FixStateMachine 放在 sections 而不是 deepRepair
FixStateMachine 不仅管理深度维修(Eye、Memory、EmoWave 等),还管理 **Clinic(诊所)****BodyModule(插线维修)** 等非深度维修状态。把它放在 `sections` 中作为表现层子系统之一,可以避免概念错位。
Fix 场景维修子模块的快照存储在 `sections`,由各自 Provider 按 `RestoreOrder` 还原
### 双入口设计:Enter vs EnterImmediate
@@ -174,26 +182,32 @@ Fix 场景各 State 的 `Enter()` 通常包含相机过渡、Timeline 播放、F
读档时 `SwitchStateImmediate` **不调用前一个状态的 Exit()**,因为读档本质是覆盖当前状态,不需要清理。
### P1 已落地的接口
### 已落地的维修 section
- `FixSnapshotDto`state、args、moduleState、eyeColorState、isSystemOn、currentRepairSystemType
- `IFixState` 接口 + `EnterImmediate()` 默认实现
- `FixStateMachine.SwitchStateImmediate()`
- `FixSystemCenter.CaptureSnapshot()` / `RestoreSnapshot()`
- `FixSnapshotProvider` 注册到 `SnapshotRegistry.EnsureInitialized`
| section id | DTO | RestoreOrder | 说明 |
| --- | --- | --- | --- |
| `punchTape` | `PunchTapeSnapshotDto` | 63 | 打孔带收藏 |
| `fix` | `FixSnapshotDto` | 65 | FixSceneDirector 宏观模式(state + args |
| `fixPanel` | `FixPanelSnapshotDto` | 66 | FixPanel 壳层 + 线缆/插头 |
| `bodyModule` | `BodyModuleSnapshotDto` | 67 | 插线模块物理态 |
| `eye` | `EyeSnapshotDto` | 68 | Eye 叙事阶段 |
### 尚未实现(P4/P5
**还原顺序**punchTape → fixcue)→ fixPanel → bodyModule → eye → screen。`fixPanel` 须在 `fix` 之后,以覆盖 Cue `EnterImmediate` 中的 `ResetPlug`
- 各 State 的 `EnterImmediate()` 具体逻辑(当前默认 `yield break`
- 深度维修子系统详细状态(BlockPuzzle grid、Cutting 进度等)→ P5 `deepRepair`
- Fix 场景读档的 Fade 时序 → P4 编排层
**维修场景门控**`FixSceneSnapshotHelper`):上述 section 仅在 `FixSystemCenter.Instance != null` 时 Capture/Restore。
### 尚未实现
- 部分 FixCue 的 `EnterImmediate()` 具体逻辑(HuoShan / BlockPuzzle / Cutting 等仍用默认空实现)
- BlockPuzzle / Memory / Cutting 等子模块的 section DTO + Provider
- `fixPanel` 扩展:灯光状态(P1)、RepairSystemManager 缩放/offsetP2
## 相关阶段
| 阶段 | 内容 |
| --- | --- |
| P2 | 基础版已落地:槽位、原子写、meta sidecar、缩略图、latest_slot、P1 测试档迁移;正式 UI 接入仍属 P6 |
| P3 | 基础版已落地:`onNodeStart` 判定、tag 白/黑名单、`no_save`、读档/暂停门控;瞬跳 content 排查与无活跃 Yarn 边界仍待补 |
| P3 | 基础版已落地:`onNodeStart` 判定、tag 白/黑名单、`no_save`、读档/暂停门控;`<<save>>` 显式存档(`CanExplicitSave`、omit anchor)已落地 |
| P4 | 基础版已落地:Provider sync/async 契约、Phase + Barrier 编排、读档自动存档抑制、Timeline Addressable 可等待恢复、验证窗口读档入口 |
| P5 | `deepRepair` 段、维修模块清单;还原模型单独定案,不默认套用 P1 Provider 协程链 |
| P5 | 维修模块 section 扩展(BlockPuzzle / Memory / Cutting 等待新增 Provider |
| P6 | 正式存 / 读档 UI、继续游戏、新游戏覆盖自动档、游戏中读档确认等玩家流程 |