From 3cdedb155ca38825dab402d58d7ddc62e29e1496 Mon Sep 17 00:00:00 2001
From: Ding Yuntian <1491671119@qq.com>
Date: Sun, 26 Jul 2026 18:07:34 +0800
Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BB=BB=E5=8A=A1=E9=9D=A2=E6=9D=BF?=
=?UTF-8?q?=E9=87=8D=E6=9E=84?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../Prefabs/FixSystemPrefabs/维修面板.prefab | 69 ++++
Assets/Prefabs/UIprefab/TaskItem.prefab | 14 +
Assets/Scripts/AssetRefs/ConstRef.cs | 1 -
.../Screen System/Core/FixPanelSystem.cs | 6 +-
.../Screen System/FixPanel/TaskPanel.cs | 354 ++++++++++++++----
.../Screen System/ScreenYarnCommand.cs | 2 +-
.../FixSystemNew/Screen System/TaskItem.cs | 14 +-
.../FixSystemNew/States/PeipeiFixCues.cs | 6 +-
Assets/Scripts/SaveSystem/README.md | 6 +-
Assets/Scripts/SaveSystem/SaveSnapshot.cs | 8 +-
10 files changed, 386 insertions(+), 94 deletions(-)
diff --git a/Assets/Prefabs/FixSystemPrefabs/维修面板.prefab b/Assets/Prefabs/FixSystemPrefabs/维修面板.prefab
index 7ae8ce31e..06c25bb66 100644
--- a/Assets/Prefabs/FixSystemPrefabs/维修面板.prefab
+++ b/Assets/Prefabs/FixSystemPrefabs/维修面板.prefab
@@ -2827,6 +2827,8 @@ Transform:
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 895638590458225172}
+ - {fileID: 910000000000000002}
+ - {fileID: 910000000000000004}
- {fileID: 2161354415544340870}
- {fileID: 930245164819552547}
- {fileID: 1768036090393189231}
@@ -2845,7 +2847,74 @@ MonoBehaviour:
m_Name:
m_EditorClassIdentifier:
taskRoot: {fileID: 895638590458225172}
+ hiddenAnchor: {fileID: 910000000000000002}
+ shownAnchor: {fileID: 910000000000000004}
taskListParent: {fileID: 2078109273994026669}
+ taskItemPrefab: {fileID: 910000000000000005, guid: 63913c6ee20b38644bf16a505dd300f2, type: 3}
+ animationDuration: 1
+ animationEase: 6
+--- !u!1 &910000000000000001
+GameObject:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ serializedVersion: 6
+ m_Component:
+ - component: {fileID: 910000000000000002}
+ m_Layer: 0
+ m_Name: TaskPanelHiddenAnchor
+ m_TagString: Untagged
+ m_Icon: {fileID: 0}
+ m_NavMeshLayer: 0
+ m_StaticEditorFlags: 0
+ m_IsActive: 1
+--- !u!4 &910000000000000002
+Transform:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 910000000000000001}
+ serializedVersion: 2
+ m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+ m_LocalPosition: {x: -10.32, y: 3.6511626, z: 0}
+ m_LocalScale: {x: 1, y: 1, z: 1}
+ m_ConstrainProportionsScale: 0
+ m_Children: []
+ m_Father: {fileID: 4912059846133439537}
+ m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
+--- !u!1 &910000000000000003
+GameObject:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ serializedVersion: 6
+ m_Component:
+ - component: {fileID: 910000000000000004}
+ m_Layer: 0
+ m_Name: TaskPanelShownAnchor
+ m_TagString: Untagged
+ m_Icon: {fileID: 0}
+ m_NavMeshLayer: 0
+ m_StaticEditorFlags: 0
+ m_IsActive: 1
+--- !u!4 &910000000000000004
+Transform:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 910000000000000003}
+ serializedVersion: 2
+ m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
+ m_LocalPosition: {x: -7.12, y: 3.6511626, z: 0}
+ m_LocalScale: {x: 1, y: 1, z: 1}
+ m_ConstrainProportionsScale: 0
+ m_Children: []
+ m_Father: {fileID: 4912059846133439537}
+ m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &2080789105181032567
GameObject:
m_ObjectHideFlags: 0
diff --git a/Assets/Prefabs/UIprefab/TaskItem.prefab b/Assets/Prefabs/UIprefab/TaskItem.prefab
index 115f25811..1ff5b5afc 100644
--- a/Assets/Prefabs/UIprefab/TaskItem.prefab
+++ b/Assets/Prefabs/UIprefab/TaskItem.prefab
@@ -11,6 +11,7 @@ GameObject:
- component: {fileID: 4156240678385147197}
- component: {fileID: 3152720343440710739}
- component: {fileID: 351969066121265812}
+ - component: {fileID: 910000000000000005}
m_Layer: 0
m_Name: TaskItem
m_TagString: Untagged
@@ -171,3 +172,16 @@ MonoBehaviour:
m_hasFontAssetChanged: 0
m_renderer: {fileID: 3152720343440710739}
m_maskType: 0
+--- !u!114 &910000000000000005
+MonoBehaviour:
+ m_ObjectHideFlags: 0
+ m_CorrespondingSourceObject: {fileID: 0}
+ m_PrefabInstance: {fileID: 0}
+ m_PrefabAsset: {fileID: 0}
+ m_GameObject: {fileID: 5370176113195622641}
+ m_Enabled: 1
+ m_EditorHideFlags: 0
+ m_Script: {fileID: 11500000, guid: 4fe106c891d8f8b448b72b805e707075, type: 3}
+ m_Name:
+ m_EditorClassIdentifier:
+ label: {fileID: 351969066121265812}
diff --git a/Assets/Scripts/AssetRefs/ConstRef.cs b/Assets/Scripts/AssetRefs/ConstRef.cs
index 3c1912efa..c8597eac8 100644
--- a/Assets/Scripts/AssetRefs/ConstRef.cs
+++ b/Assets/Scripts/AssetRefs/ConstRef.cs
@@ -56,7 +56,6 @@ namespace AibisDream.Utility
public const string CutLinePrefabName = "Prefab/CutLine";
- public const string TaskItemName = "Prefab/TaskItem";
public const string ActorPrefabName = "Prefab/ActorAnima";
public const string SpriteActorPrefabName = "Prefab/SpriteActor";
diff --git a/Assets/Scripts/FixSystemNew/Screen System/Core/FixPanelSystem.cs b/Assets/Scripts/FixSystemNew/Screen System/Core/FixPanelSystem.cs
index 8d320af29..1392ed60d 100644
--- a/Assets/Scripts/FixSystemNew/Screen System/Core/FixPanelSystem.cs
+++ b/Assets/Scripts/FixSystemNew/Screen System/Core/FixPanelSystem.cs
@@ -102,7 +102,7 @@ namespace AibisDream.FixSystem
isStartupPrepared = true;
targetLightState = LightState.Normal;
ApplySystemOnImmediate(false);
- taskPanel?.HidePanelImmediate();
+ taskPanel?.SetVisible(false, immediate: true);
}
///
@@ -205,7 +205,7 @@ namespace AibisDream.FixSystem
if (taskPanel != null)
{
- taskPanel.CaptureSnapshot(out dto.isTaskPanelVisible, dto.tasks);
+ taskPanel.CaptureSnapshot(out dto.isTaskPanelRequestedVisible, dto.tasks);
}
return dto;
@@ -235,7 +235,7 @@ namespace AibisDream.FixSystem
GetRepairPanel()?.ApplyCableSnapshot(dto.isCableRetracted, dto.pluggedModuleName);
- taskPanel?.ApplySnapshot(dto.isTaskPanelVisible, dto.tasks, immediate: true);
+ taskPanel?.ApplySnapshot(dto.isTaskPanelRequestedVisible, dto.tasks);
}
/// 读档终态:跳过 StartAllSystems 动画,直接写面板壳层状态。
diff --git a/Assets/Scripts/FixSystemNew/Screen System/FixPanel/TaskPanel.cs b/Assets/Scripts/FixSystemNew/Screen System/FixPanel/TaskPanel.cs
index ecdf3dee3..21d4f7aa5 100644
--- a/Assets/Scripts/FixSystemNew/Screen System/FixPanel/TaskPanel.cs
+++ b/Assets/Scripts/FixSystemNew/Screen System/FixPanel/TaskPanel.cs
@@ -1,121 +1,153 @@
-using System.Collections.Generic;
-using AibisDream.Framework;
+using System.Collections.Generic;
using AibisDream.SaveSystem;
-using AibisDream.Utility;
-using TMPro;
+using DG.Tweening;
using UnityEngine;
using UnityEngine.UI;
-using DG.Tweening;
namespace AibisDream.FixSystem
{
public class TaskPanel : MonoBehaviour, ILineView
{
- private const float HiddenLocalX = -10.32f;
- private const float ShownLocalX = -7.12f;
-
- #region 索引
-
+ [Header("面板位置")]
[SerializeField] private Transform taskRoot;
- [SerializeField] private Transform taskListParent;
- private GameObject _taskItemPrefab;
- private readonly Dictionary _taskDict = new();
+ [SerializeField] private Transform hiddenAnchor;
+ [SerializeField] private Transform shownAnchor;
- #endregion
+ [Header("任务列表")]
+ [SerializeField] private RectTransform taskListParent;
+ [SerializeField] private TaskItem taskItemPrefab;
+
+ [Header("动画")]
+ [SerializeField, Min(0f)] private float animationDuration = 1f;
+ [SerializeField] private Ease animationEase = Ease.OutQuad;
+
+ private readonly List _tasks = new();
+ private Tween _moveTween;
+ private bool _requestedVisible;
+ private bool _temporarilyHidden;
+
+ public bool RequestedVisible => _requestedVisible;
+ public bool EffectiveVisible => _requestedVisible && !_temporarilyHidden;
+
+ private sealed class TaskEntry
+ {
+ public string LineId;
+ public string Text;
+ public TaskItem View;
+ }
private void Awake()
{
- _taskItemPrefab = ResourceKit.LoadAssetSync(ConstRef.TaskItemName);
+ ValidateConfiguration();
}
- public bool IsPanelVisible => Mathf.Approximately(taskRoot.localPosition.x, ShownLocalX);
-
- public void ShowPanel()
+ private void OnEnable()
{
- taskRoot.DOLocalMoveX(ShownLocalX, 1f);
+ RefreshVisual(immediate: true);
}
- /// 动画收起面板(与 ShowPanel 对称)。
- public void HidePanel()
+ private void OnDisable()
{
- taskRoot.DOKill();
- taskRoot.DOLocalMoveX(HiddenLocalX, 1f);
+ KillMoveTween();
}
- public void HidePanelImmediate()
+ public void SetVisible(bool visible, bool immediate = false)
{
- taskRoot.DOKill();
- SetPanelVisibleImmediate(false);
+ if (_requestedVisible == visible)
+ {
+ if (immediate)
+ {
+ RefreshVisual(immediate: true);
+ }
+
+ return;
+ }
+
+ var wasEffectivelyVisible = EffectiveVisible;
+ _requestedVisible = visible;
+
+ if (wasEffectivelyVisible != EffectiveVisible || immediate)
+ {
+ RefreshVisual(immediate);
+ }
}
- private bool _restoreVisibleAfterCollapse;
-
- /// 临时收起面板(如进入 Memory 模式),记录之前是否展开,供 RestoreCollapsedPanel 恢复。
- public void CollapsePanelTemporary(bool immediate = false)
+ public void SetTemporarilyHidden(bool hidden, bool immediate = false)
{
- _restoreVisibleAfterCollapse = IsPanelVisible;
- if (!_restoreVisibleAfterCollapse) return;
- if (immediate) HidePanelImmediate();
- else HidePanel();
- }
+ if (_temporarilyHidden == hidden)
+ {
+ if (immediate)
+ {
+ RefreshVisual(immediate: true);
+ }
- /// 按 CollapsePanelTemporary 记录的状态恢复面板(之前未展开则不做任何事)。
- public void RestoreCollapsedPanel()
- {
- if (!_restoreVisibleAfterCollapse) return;
- _restoreVisibleAfterCollapse = false;
- ShowPanel();
+ return;
+ }
+
+ var wasEffectivelyVisible = EffectiveVisible;
+ _temporarilyHidden = hidden;
+
+ if (wasEffectivelyVisible != EffectiveVisible || immediate)
+ {
+ RefreshVisual(immediate);
+ }
}
public void CompleteTask(string lineId)
{
- if (_taskDict.Remove(lineId, out var taskItem))
+ var index = FindTaskIndex(lineId);
+ if (index < 0)
{
- Destroy(taskItem);
+ return;
}
+
+ DestroyTaskView(_tasks[index].View);
+ _tasks.RemoveAt(index);
+ MarkTaskLayoutDirty();
}
public void ClearTasks()
{
- foreach (var task in _taskDict)
+ foreach (var task in _tasks)
{
- Destroy(task.Value);
+ DestroyTaskView(task.View);
}
- _taskDict.Clear();
+
+ _tasks.Clear();
+ MarkTaskLayoutDirty();
}
public void RunLine(LineSyncToken token)
{
- if (_taskDict.ContainsKey(token.lineInfo.lineId))
+ var lineId = token.lineInfo.lineId;
+ if (string.IsNullOrWhiteSpace(lineId))
{
- EnumEventSystem.Global.Send(DialogEventEnum.LineShown);
- token.ForceAdvance();
- return;
+ Debug.LogWarning($"[{nameof(TaskPanel)}] 忽略缺少 lineId 的任务文本。", this);
+ }
+ else if (FindTaskIndex(lineId) < 0)
+ {
+ AddTaskItem(lineId, token.lineInfo.lineText);
}
- AddTaskItem(token.lineInfo.lineId, $"\u25cf {token.lineInfo.lineText}");
- token.TextStart();
- token.TextShown();
- token.ForceAdvance();
+ CompleteLineImmediately(token);
}
- public void CaptureSnapshot(out bool isPanelVisible, List tasks)
+ public void CaptureSnapshot(out bool requestedVisible, List tasks)
{
- isPanelVisible = IsPanelVisible;
+ requestedVisible = RequestedVisible;
tasks.Clear();
- foreach (var kv in _taskDict)
+ foreach (var task in _tasks)
{
- var text = kv.Value.GetComponent()?.text ?? string.Empty;
tasks.Add(new TaskEntrySnapshotDto
{
- lineId = kv.Key,
- text = text
+ lineId = task.LineId,
+ text = task.Text
});
}
}
- public void ApplySnapshot(bool isPanelVisible, List tasks, bool immediate)
+ public void ApplySnapshot(bool requestedVisible, List tasks)
{
ClearTasks();
@@ -123,40 +155,208 @@ namespace AibisDream.FixSystem
{
foreach (var entry in tasks)
{
- if (string.IsNullOrEmpty(entry.lineId))
+ if (entry == null || string.IsNullOrWhiteSpace(entry.lineId))
{
+ Debug.LogWarning($"[{nameof(TaskPanel)}] 跳过缺少 lineId 的任务快照。", this);
continue;
}
- AddTaskItem(entry.lineId, entry.text);
+ if (FindTaskIndex(entry.lineId) >= 0)
+ {
+ Debug.LogWarning($"[{nameof(TaskPanel)}] 跳过重复任务快照 '{entry.lineId}'。", this);
+ continue;
+ }
+
+ AddTaskItem(entry.lineId, entry.text ?? string.Empty);
}
}
- if (immediate)
+ SetVisible(requestedVisible, immediate: true);
+ }
+
+ private void RefreshVisual(bool immediate)
+ {
+ KillMoveTween();
+
+ var visible = EffectiveVisible;
+ if (visible)
{
- taskRoot.DOKill();
- SetPanelVisibleImmediate(isPanelVisible);
+ SetTaskTextVisible(true);
+ MarkTaskLayoutDirty();
}
- else if (isPanelVisible)
+
+ if (taskRoot == null || hiddenAnchor == null || shownAnchor == null)
{
- ShowPanel();
+ if (!visible)
+ {
+ SetTaskTextVisible(false);
+ }
+
+ return;
}
+
+ var targetPosition = visible
+ ? shownAnchor.localPosition
+ : hiddenAnchor.localPosition;
+
+ if (immediate || animationDuration <= 0f)
+ {
+ taskRoot.localPosition = targetPosition;
+ if (!visible)
+ {
+ SetTaskTextVisible(false);
+ }
+
+ return;
+ }
+
+ var tween = taskRoot
+ .DOLocalMove(targetPosition, animationDuration)
+ .SetEase(animationEase);
+
+ _moveTween = tween;
+ tween.OnComplete(() =>
+ {
+ if (_moveTween != tween)
+ {
+ return;
+ }
+
+ _moveTween = null;
+ if (!EffectiveVisible)
+ {
+ SetTaskTextVisible(false);
+ }
+ });
}
private void AddTaskItem(string lineId, string text)
{
- var taskItem = Instantiate(_taskItemPrefab, taskListParent);
- var task = taskItem.GetComponent();
- task.text = text;
- _taskDict[lineId] = taskItem;
- LayoutRebuilder.ForceRebuildLayoutImmediate(taskListParent.GetComponent());
+ TaskItem view = null;
+ if (taskItemPrefab == null || taskListParent == null)
+ {
+ Debug.LogError(
+ $"[{nameof(TaskPanel)}] 无法创建任务 '{lineId}':TaskItem Prefab 或任务列表父节点未配置。",
+ this);
+ }
+ else
+ {
+ view = Instantiate(taskItemPrefab, taskListParent);
+ view.SetText(text);
+ }
+
+ _tasks.Add(new TaskEntry
+ {
+ LineId = lineId,
+ Text = text,
+ View = view
+ });
+
+ MarkTaskLayoutDirty();
}
- private void SetPanelVisibleImmediate(bool visible)
+ private int FindTaskIndex(string lineId)
{
- var pos = taskRoot.localPosition;
- pos.x = visible ? ShownLocalX : HiddenLocalX;
- taskRoot.localPosition = pos;
+ if (string.IsNullOrEmpty(lineId))
+ {
+ return -1;
+ }
+
+ for (var i = 0; i < _tasks.Count; i++)
+ {
+ if (_tasks[i].LineId == lineId)
+ {
+ return i;
+ }
+ }
+
+ return -1;
+ }
+
+ private static void CompleteLineImmediately(LineSyncToken token)
+ {
+ token.TextStart();
+ token.TextShown();
+ token.ForceAdvance();
+ }
+
+ private static void DestroyTaskView(TaskItem view)
+ {
+ if (view == null)
+ {
+ return;
+ }
+
+ view.gameObject.SetActive(false);
+ Destroy(view.gameObject);
+ }
+
+ private void SetTaskTextVisible(bool visible)
+ {
+ if (taskListParent != null && taskListParent.gameObject.activeSelf != visible)
+ {
+ taskListParent.gameObject.SetActive(visible);
+ }
+ }
+
+ private void MarkTaskLayoutDirty()
+ {
+ if (taskListParent != null)
+ {
+ LayoutRebuilder.MarkLayoutForRebuild(taskListParent);
+ }
+ }
+
+ private void KillMoveTween()
+ {
+ if (_moveTween == null)
+ {
+ return;
+ }
+
+ var tween = _moveTween;
+ _moveTween = null;
+ tween.Kill();
+ }
+
+ private void ValidateConfiguration()
+ {
+ if (taskRoot == null)
+ {
+ Debug.LogError($"[{nameof(TaskPanel)}] {name} 未配置 Task Root。", this);
+ }
+
+ if (hiddenAnchor == null)
+ {
+ Debug.LogError($"[{nameof(TaskPanel)}] {name} 未配置 Hidden Anchor。", this);
+ }
+
+ if (shownAnchor == null)
+ {
+ Debug.LogError($"[{nameof(TaskPanel)}] {name} 未配置 Shown Anchor。", this);
+ }
+
+ if (taskRoot != null
+ && hiddenAnchor != null
+ && shownAnchor != null
+ && (taskRoot.parent != hiddenAnchor.parent || taskRoot.parent != shownAnchor.parent))
+ {
+ Debug.LogError($"[{nameof(TaskPanel)}] {name} 的 Task Root 与两个 Anchor 必须拥有同一个父节点。", this);
+ }
+
+ if (taskListParent == null)
+ {
+ Debug.LogError($"[{nameof(TaskPanel)}] {name} 未配置任务列表父节点。", this);
+ }
+
+ if (taskItemPrefab == null)
+ {
+ Debug.LogError($"[{nameof(TaskPanel)}] {name} 未配置 TaskItem Prefab。", this);
+ }
+ else if (!taskItemPrefab.IsConfigured)
+ {
+ Debug.LogError($"[{nameof(TaskPanel)}] {name} 的 TaskItem Prefab 未绑定文本组件。", this);
+ }
}
}
}
diff --git a/Assets/Scripts/FixSystemNew/Screen System/ScreenYarnCommand.cs b/Assets/Scripts/FixSystemNew/Screen System/ScreenYarnCommand.cs
index a7672371b..f6015e7fd 100644
--- a/Assets/Scripts/FixSystemNew/Screen System/ScreenYarnCommand.cs
+++ b/Assets/Scripts/FixSystemNew/Screen System/ScreenYarnCommand.cs
@@ -37,7 +37,7 @@ namespace AibisDream
[YarnCommand("show_task_panel")]
public static void ShowTaskPanel()
{
- TaskPanel.ShowPanel();
+ TaskPanel?.SetVisible(true);
}
#endregion
diff --git a/Assets/Scripts/FixSystemNew/Screen System/TaskItem.cs b/Assets/Scripts/FixSystemNew/Screen System/TaskItem.cs
index e5bccdbcb..7350193eb 100644
--- a/Assets/Scripts/FixSystemNew/Screen System/TaskItem.cs
+++ b/Assets/Scripts/FixSystemNew/Screen System/TaskItem.cs
@@ -1,13 +1,23 @@
using TMPro;
using UnityEngine;
-namespace AibisDream
+namespace AibisDream.FixSystem
{
public class TaskItem : MonoBehaviour
{
+ [SerializeField] private TMP_Text label;
+
+ public bool IsConfigured => label != null;
+
public void SetText(string value)
{
- GetComponent().text = $"\u25cf {value}";
+ if (label == null)
+ {
+ Debug.LogError($"[{nameof(TaskItem)}] {name} 未绑定文本组件。", this);
+ return;
+ }
+
+ label.text = $"\u25cf {value}";
}
}
}
diff --git a/Assets/Scripts/FixSystemNew/States/PeipeiFixCues.cs b/Assets/Scripts/FixSystemNew/States/PeipeiFixCues.cs
index 028b913e4..a71fb5793 100644
--- a/Assets/Scripts/FixSystemNew/States/PeipeiFixCues.cs
+++ b/Assets/Scripts/FixSystemNew/States/PeipeiFixCues.cs
@@ -106,7 +106,7 @@ namespace AibisDream.FixSystem
float duration = 0.5f;
var memorySystem = FixSystemCenter.SystemDic.Get();
// 进入Memory前收起Task面板
- FixPanelSystem.Instance.TaskPanel?.CollapsePanelTemporary();
+ FixPanelSystem.Instance.TaskPanel?.SetTemporarilyHidden(true);
// 先切BodyModule
if (!CameraKit.Instance.EqualToCameraState(CameraEnum.BodyModule))
{
@@ -126,7 +126,7 @@ namespace AibisDream.FixSystem
{
var memorySystem = FixSystemCenter.SystemDic.Get();
- FixPanelSystem.Instance.TaskPanel?.CollapsePanelTemporary(immediate: true);
+ FixPanelSystem.Instance.TaskPanel?.SetTemporarilyHidden(true, immediate: true);
yield return memorySystem.DropMemoryProjector();
FixPanelSystem.GetRepairPanel()?.PullUpCable();
yield return CameraKit.Instance.SwitchCamera(CameraEnum.Memory, true);
@@ -145,7 +145,7 @@ namespace AibisDream.FixSystem
yield return CameraKit.Instance.SwitchCamera(CameraEnum.BodyModule);
memorySystem.PullMemoryProjector();
// 退出Memory后恢复Task面板
- FixPanelSystem.Instance.TaskPanel?.RestoreCollapsedPanel();
+ FixPanelSystem.Instance.TaskPanel?.SetTemporarilyHidden(false);
}
}
}
diff --git a/Assets/Scripts/SaveSystem/README.md b/Assets/Scripts/SaveSystem/README.md
index c0c7b793d..59d32be19 100644
--- a/Assets/Scripts/SaveSystem/README.md
+++ b/Assets/Scripts/SaveSystem/README.md
@@ -146,7 +146,7 @@ Postflight 校验
Provider 使用 `ISyncSnapshotProvider` 或 `IAsyncSnapshotProvider` 显式声明同步/异步恢复;异步 Provider 必须把等待过程返回给编排层,禁止内部 fire-and-forget。
-## 快照 JSON 结构(schemaVersion = 1)
+## 快照 JSON 结构(schemaVersion = 2)
| 字段 | 含义 |
| --- | --- |
@@ -191,11 +191,11 @@ Fix 场景各 State 的 `Enter()` 通常包含相机过渡、Timeline 播放、F
| --- | --- | --- | --- |
| `punchTape` | `PunchTapeSnapshotDto` | 63 | 打孔带收藏 |
| `fix` | `FixSnapshotDto` | 65 | FixSceneDirector 宏观模式(state + args) |
-| `fixPanel` | `FixPanelSnapshotDto` | 66 | FixPanel 壳层 + 线缆/插头 + TaskPanel(展开状态与任务列表) |
+| `fixPanel` | `FixPanelSnapshotDto` | 66 | FixPanel 壳层 + 线缆/插头 + TaskPanel(请求展开状态与任务列表) |
| `bodyModule` | `BodyModuleSnapshotDto` | 67 | 插线模块物理态 |
| `eye` | `EyeSnapshotDto` | 68 | Eye 叙事阶段 |
-**还原顺序**:punchTape → fix(cue)→ fixPanel → bodyModule → eye → showcase → day2SleepPresentation → playTool → screen。`fixPanel` 须在 `fix` 之后,以覆盖 Cue `EnterImmediate` 中的 `ResetPlug`;D2 动态表现须在通用 Showcase 图片之后恢复,才能叠加虚焦、缩放或场景专属动画。
+**还原顺序**:punchTape → fix(cue)→ fixPanel → bodyModule → eye → showcase → day2SleepPresentation → playTool → screen。`fixPanel` 须在 `fix` 之后,以覆盖 Cue `EnterImmediate` 中的 `ResetPlug`,并让 Memory Cue 先建立 TaskPanel 临时隐藏状态;D2 动态表现须在通用 Showcase 图片之后恢复,才能叠加虚焦、缩放或场景专属动画。
**维修场景门控**(`FixSceneSnapshotHelper`):上述 section 仅在 `FixSystemCenter.Instance != null` 时 Capture/Restore。
diff --git a/Assets/Scripts/SaveSystem/SaveSnapshot.cs b/Assets/Scripts/SaveSystem/SaveSnapshot.cs
index daba7a69b..7e9f7d46b 100644
--- a/Assets/Scripts/SaveSystem/SaveSnapshot.cs
+++ b/Assets/Scripts/SaveSystem/SaveSnapshot.cs
@@ -9,7 +9,7 @@ namespace AibisDream.SaveSystem
///
public static class SaveSnapshotSchema
{
- public const int CurrentVersion = 1;
+ public const int CurrentVersion = 2;
}
///
@@ -269,7 +269,7 @@ namespace AibisDream.SaveSystem
/// Yarn 行 id,如 line:01dade5。
public string lineId;
- /// 存档时 UI 显示的完整文本(含 ● 前缀)。
+ /// 存档时已完成 substitutions 的本地化文本,不含 UI 圆点前缀。
public string text;
}
@@ -290,8 +290,8 @@ namespace AibisDream.SaveSystem
/// 插头插入的 BodyModule 名(data.moduleName);null/空 = 未插入。
public string pluggedModuleName;
- /// TaskPanel 是否处于展开位(show_task_panel 后)。
- public bool isTaskPanelVisible;
+ /// 剧情是否要求 TaskPanel 展开;Memory 等临时隐藏状态不写入存档。
+ public bool isTaskPanelRequestedVisible;
/// TaskPanel 当前未完成任务列表(保持插入顺序)。
public List tasks = new();