多轮审查和修复

This commit is contained in:
2026-05-12 15:34:08 +08:00
parent f55d2a57c3
commit ebbbb7332e
805 changed files with 838724 additions and 1905 deletions

View File

@@ -0,0 +1,76 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using BaseGames.Core.Save;
namespace BaseGames.Tutorial
{
/// <summary>
/// 教程提示管理器(架构 21_LiquidPuzzleModule §17
/// 通过 ServiceLocator 注册,实现 ISaveable 将已完成提示 ID 持久化。
/// ShowHint若 ID 已完成则跳过;否则显示,并在 duration 秒后自动隐藏。
/// CompleteHint标记为已完成写回 SaveData。
/// </summary>
public class TutorialManager : MonoBehaviour, ISaveable, ITutorialService
{
[SerializeField] private TutorialHintUI _hintUI;
private readonly HashSet<string> _completedHints = new();
// ── Unity 生命周期 ────────────────────────────────────
private void Awake()
{
if (BaseGames.Core.ServiceLocator.GetOrDefault<ITutorialService>() != null) { Destroy(gameObject); return; }
BaseGames.Core.ServiceLocator.Register<ITutorialService>(this);
// 生命周期由 Persistent 场景根 GameObject 统一管理,不在此调用 DontDestroyOnLoad
}
private void OnDestroy()
{
BaseGames.Core.ServiceLocator.Unregister<ITutorialService>(this);
}
// ── 公共 API ──────────────────────────────────────────────────────
/// <summary>
/// 显示提示。若 hintId 已完成则忽略。
/// <paramref name="hintId"/>: 唯一提示 ID可作为去重键和保存键
/// <paramref name="text"/>: 本地化后的显示文字。
/// <paramref name="duration"/>: 自动消隐秒数(≤ 0 则不自动消隐)。
/// </summary>
public void ShowHint(string hintId, string text, float duration = 4f)
{
if (_completedHints.Contains(hintId)) return;
if (_hintUI == null) return;
_hintUI.Show(text, duration);
}
/// <summary>标记提示为已完成,并自动隐藏当前显示中的提示。</summary>
public void CompleteHint(string hintId)
{
if (_completedHints.Add(hintId))
{
_hintUI?.Hide();
// 持久化由 ISaveable.OnSave 统一处理,此处仅更新内存状态
}
}
/// <summary>查询指定提示是否已完成。</summary>
public bool IsHintCompleted(string hintId) => _completedHints.Contains(hintId);
// ── ISaveable ─────────────────────────────────────────────────────
public void OnSave(SaveData data)
{
if (data?.Tutorial == null) return;
data.Tutorial.CompletedHintIds.Clear();
data.Tutorial.CompletedHintIds.AddRange(_completedHints);
}
public void OnLoad(SaveData data)
{
_completedHints.Clear();
if (data?.Tutorial == null) return;
foreach (var id in data.Tutorial.CompletedHintIds)
_completedHints.Add(id);
}
}
}