using System.Collections.Generic; using UnityEngine; namespace ShrinkTutorial { [CreateAssetMenu(fileName = "ShrinkTutorialDatabase", menuName = "ShrinkSDK/引导/教程数据库")] public class ShrinkTutorialDatabase : ScriptableObject { [SerializeField] private List tutorials = new(); private Dictionary _cache; public IReadOnlyList Tutorials => tutorials; public bool TryGetTutorial(string tutorialId, out ShrinkTutorialData tutorial) { EnsureCache(); return _cache.TryGetValue(tutorialId, out tutorial); } public List Validate() { var issues = new List(); var ids = new HashSet(); foreach (var tutorial in tutorials) { if (!tutorial) { issues.Add("存在空的教程资源引用。"); continue; } if (string.IsNullOrWhiteSpace(tutorial.tutorialId)) { issues.Add($"教程资源 {tutorial.name} 缺少 tutorialId。"); } else if (!ids.Add(tutorial.tutorialId)) { issues.Add($"tutorialId 重复: {tutorial.tutorialId}"); } if (tutorial.steps == null || tutorial.steps.Count == 0) { issues.Add($"教程 {tutorial.tutorialId} 没有任何步骤。"); continue; } for (var i = 0; i < tutorial.steps.Count; i++) { var step = tutorial.steps[i]; if (step == null) { issues.Add($"教程 {tutorial.tutorialId} 第 {i + 1} 步为空。"); continue; } if (step.targetMode == ShrinkTutorialTargetMode.Path && string.IsNullOrWhiteSpace(step.targetPath)) issues.Add($"教程 {tutorial.tutorialId} 第 {i + 1} 步缺少 targetPath。"); if (step.targetMode == ShrinkTutorialTargetMode.AnchorId && string.IsNullOrWhiteSpace(step.anchorId)) issues.Add($"教程 {tutorial.tutorialId} 第 {i + 1} 步缺少 anchorId。"); if (step.completeCondition == ShrinkTutorialCompleteCondition.CustomEvent && string.IsNullOrWhiteSpace(step.customEventName)) issues.Add($"教程 {tutorial.tutorialId} 第 {i + 1} 步使用 CustomEvent 但未填写 customEventName。"); } } return issues; } private void OnValidate() { _cache = null; } private void EnsureCache() { if (_cache != null) return; _cache = new Dictionary(); foreach (var tutorial in tutorials) { if (!tutorial || string.IsNullOrWhiteSpace(tutorial.tutorialId)) continue; _cache[tutorial.tutorialId] = tutorial; } } } }