87 lines
3.6 KiB
C#
87 lines
3.6 KiB
C#
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);
|
||
}
|
||
|
||
private void OnEnable()
|
||
{
|
||
BaseGames.Core.ServiceLocator.GetOrDefault<BaseGames.Core.Save.ISaveableRegistry>()?.Register(this);
|
||
}
|
||
|
||
private void OnDisable()
|
||
{
|
||
BaseGames.Core.ServiceLocator.GetOrDefault<BaseGames.Core.Save.ISaveableRegistry>()?.Unregister(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);
|
||
}
|
||
}
|
||
}
|