diff --git a/Assets/Scripts/SaveSystem/README.md b/Assets/Scripts/SaveSystem/README.md index b955c9c5f..d4ad2fb12 100644 --- a/Assets/Scripts/SaveSystem/README.md +++ b/Assets/Scripts/SaveSystem/README.md @@ -49,6 +49,22 @@ Yarn 脚本: - 绕过 tag / `no_save` 的自动判定(`CanExplicitSave`);仍受读档中、暂停、SuppressAutoSave 门控。 - 与 `OnNodeStart` 分工:常规 `hub` / `linear` / `content` 仍靠节点进入自动存;`<>` 用于即将进入无对话 / Fix 交互等 `OnNodeStart` 覆盖不到的边界。 +### P3 自动档边界(含 detour 去重) + +`DialogController.OnNodeStart` → `SavePointEvaluator.OnNodeStartForAutoSave` → 通过后 `AutoSaveRoutine`。 + +判定顺序: + +1. 全局门控:`IsRestoring` / `IsAutoSaveSuppressed` / `GameManager.pause` +2. **Fresh vs detour 续跑**:同一 `YarnProject` 下,若节点名已在 `InProgressNodes`(尚未 `onNodeComplete`)→ `DetourResume`,**不自动存**(避免 detour 返回父节点时重复写盘) +3. 将节点加入 `InProgressNodes`,再走 tag / `no_save` 白黑名单(`hub` / `linear` / `content` 允许;`detour` / `function` 等禁止) + +`OnNodeComplete` 将节点移出 `InProgressNodes`。`StartDialog` / `LoadDialog` 切换 `YarnProject.name` 时、`StopDialog` 时重置集合。读档重进 anchor 走 `OnRestoreEnterNode`(只标记 InProgress,不写盘)。 + +`CanAutoSave()` 仍仅做 tag + 全局门控,**不含** detour 判定(供 `TryAutoSave` 等无节点进入上下文的路径)。显式 `<>` / 手动档复制不经过 visit 判定。 + +逻辑集中在 `SavePointEvaluator.cs`,**不新增**独立 Tracker 文件。 + 正式槽位路径:`persistentDataPath/AllOurBrokenParts/saves/slot_x/{snapshot.json, meta.json, thumbnail.png}` P1 测试落盘路径:`persistentDataPath/AllOurBrokenParts/snapshot_test/latest_snapshot.json`(首次访问槽位系统时会尝试迁移到 `slot_0`) @@ -117,6 +133,7 @@ Phase 1 场景加载(Barrier:LoadSceneAsync)← 框架直管,不走 Pro Phase 1.5 设置章节 SO(sync)← 框架直管,从 anchor.sceneSoName 读取 ↓ Phase 2 env / actor / audio / timeline / fix / screen(Provider 按 RestoreOrder) + └─ timeline:`Stopped` = untouched(从未 Evaluate),读档仅还原 `isActive`,不 Reset/Evaluate ↓ Phase 2′ 可选 Barrier(如 Timeline Addressable 须显式等待) ↓ @@ -188,7 +205,7 @@ Fix 场景各 State 的 `Enter()` 通常包含相机过渡、Timeline 播放、F | --- | --- | --- | --- | | `punchTape` | `PunchTapeSnapshotDto` | 63 | 打孔带收藏 | | `fix` | `FixSnapshotDto` | 65 | FixSceneDirector 宏观模式(state + args) | -| `fixPanel` | `FixPanelSnapshotDto` | 66 | FixPanel 壳层 + 线缆/插头 | +| `fixPanel` | `FixPanelSnapshotDto` | 66 | FixPanel 壳层 + 线缆/插头 + TaskPanel(展开状态与任务列表) | | `bodyModule` | `BodyModuleSnapshotDto` | 67 | 插线模块物理态 | | `eye` | `EyeSnapshotDto` | 68 | Eye 叙事阶段 | @@ -200,14 +217,14 @@ Fix 场景各 State 的 `Enter()` 通常包含相机过渡、Timeline 播放、F - 部分 FixCue 的 `EnterImmediate()` 具体逻辑(HuoShan / BlockPuzzle / Cutting 等仍用默认空实现) - BlockPuzzle / Memory / Cutting 等子模块的 section DTO + Provider -- `fixPanel` 扩展:灯光状态(P1)、RepairSystemManager 缩放/offset(P2) +- `fixPanel` 扩展:灯光状态(P1)、RepairSystemManager 缩放/offset(P2);ScreenPanel 日志文本 ## 相关阶段 | 阶段 | 内容 | | --- | --- | | P2 | 基础版已落地:槽位、原子写、meta sidecar、缩略图、latest_slot、P1 测试档迁移;正式 UI 接入仍属 P6 | -| P3 | 基础版已落地:`onNodeStart` 判定、tag 白/黑名单、`no_save`、读档/暂停门控;`<>` 显式存档(`CanExplicitSave`、omit anchor)已落地 | +| P3 | 基础版已落地:`onNodeStart` 判定、tag 白/黑名单、`no_save`、读档/暂停门控、**detour 返回 InProgress 去重**;`<>` 显式存档(`CanExplicitSave`、omit anchor)已落地 | | P4 | 基础版已落地:Provider sync/async 契约、Phase + Barrier 编排、读档自动存档抑制、Timeline Addressable 可等待恢复、验证窗口读档入口 | | P5 | 维修子模块 section 扩展(BlockPuzzle / Memory / Cutting 等待新增 Provider) | | P6 | 正式存 / 读档 UI、继续游戏、新游戏覆盖自动档、游戏中读档确认等玩家流程 | diff --git a/Docs/存档系统设计方案.md b/Docs/存档系统设计方案.md index 8f56525ea..a9ad32683 100644 --- a/Docs/存档系统设计方案.md +++ b/Docs/存档系统设计方案.md @@ -241,8 +241,10 @@ P7 横切 ### P3 可存点判定层(基础版已落地) -- `DialogController.OnNodeStart` 更新当前 node/tags 后调用 `SavePointEvaluator.CanAutoSave()`,通过后执行 `SaveRestoreOrchestrator.AutoSaveRoutine(nodeName)`。 -- `SavePointEvaluator` 当前规则:`hub` / `linear` / `content` 默认允许;`start` / `init` / `function` / `detour` / `center` / `performance` / `event` / `end` 默认禁止;`no_save` 覆盖一切并禁止 **OnNodeStart 自动存**。 +- `DialogController.OnNodeStart` 更新当前 node/tags 后调用 `SavePointEvaluator.OnNodeStartForAutoSave()`,通过后执行 `SaveRestoreOrchestrator.AutoSaveRoutine(nodeName)`。 +- **Fresh 进入 vs detour 续跑**:`SavePointEvaluator` 按 `yarnProjectId` 维护 `InProgressNodes`;节点尚未 `onNodeComplete` 时再次 `onNodeStart`(Yarn detour 返回父节点)→ `DetourResume`,跳过自动存。`OnNodeComplete` 移出集合;切换 YarnProject / `StopDialog` 重置;读档 anchor 重进仅 `OnRestoreEnterNode` 标记,不写盘。 +- **tag 规则**:`hub` / `linear` / `content` 默认允许;`start` / `init` / `function` / `detour` / `center` / `performance` / `event` / `end` 默认禁止;`no_save` 覆盖一切并禁止 **OnNodeStart 自动存**。 +- 自动档边界 = **Fresh OnNodeStart** 且 tag 判定通过且非 `DetourResume`(不区分 hub / content / linear 的额外终身去重)。 - Yarn `<>`(`SaveYarnCommand`)走 `CanExplicitSave`:仅全局门控,默认 omit anchor;用于节点末尾进入无对话 / Fix 交互等边界。 - `SaveRestoreOrchestrator.IsRestoring` 与 `GameManager.state.isInPause` 会阻止自动保存与显式 save,避免读档中覆盖自动档。 - `CreateManualSlot` 复用 `CanManualSave`:`slot_0` 存在且通过全局门控即可复制(含显式 `<>` 写盘后的手动档)。