using UnityEngine; using System.Collections.Generic; public class PuzzleManager : MonoBehaviour { private static PuzzleManager _instance; public static PuzzleManager Instance { get { if (_instance == null) { _instance = FindAnyObjectByType(); if (_instance == null) { var go = new GameObject("PuzzleManager"); _instance = go.AddComponent(); DontDestroyOnLoad(go); } } return _instance; } } private HashSet completedSteps = new HashSet(); private HashSet unlockedSteps = new HashSet(); // Registration for ObjectiveStepBehaviour private Dictionary stepBehaviours = new Dictionary(); // Runtime dependency graph private Dictionary> runtimeDependencies = new Dictionary>(); void Awake() { if (_instance != null && _instance != this) { Destroy(gameObject); return; } _instance = this; DontDestroyOnLoad(gameObject); } public void RegisterStepBehaviour(ObjectiveStepBehaviour behaviour) { if (behaviour?.stepData == null) return; if (!stepBehaviours.ContainsKey(behaviour.stepData)) { stepBehaviours.Add(behaviour.stepData, behaviour); Debug.Log($"[Puzzles] Registered step: {behaviour.stepData.stepId} on {behaviour.gameObject.name}"); } } public void UnregisterStepBehaviour(ObjectiveStepBehaviour behaviour) { if (behaviour?.stepData == null) return; stepBehaviours.Remove(behaviour.stepData); Debug.Log($"[Puzzles] Unregistered step: {behaviour.stepData.stepId} on {behaviour.gameObject.name}"); } void Start() { BuildRuntimeDependencies(); UnlockInitialSteps(); } private void BuildRuntimeDependencies() { runtimeDependencies.Clear(); foreach (var step in stepBehaviours.Keys) { runtimeDependencies[step] = new List(); } foreach (var step in stepBehaviours.Keys) { foreach (var unlocked in step.unlocks) { if (!runtimeDependencies.ContainsKey(unlocked)) runtimeDependencies[unlocked] = new List(); runtimeDependencies[unlocked].Add(step); Debug.Log($"[Puzzles] Step {unlocked.stepId} depends on {step.stepId}"); } } Debug.Log($"[Puzzles] Runtime dependencies built. Total steps: {stepBehaviours.Count}"); } private void UnlockInitialSteps() { foreach (var step in stepBehaviours.Keys) { if (runtimeDependencies[step].Count == 0) { Debug.Log($"[Puzzles] Initial step unlocked: {step.stepId}"); UnlockStep(step); } } } public void OnStepCompleted(PuzzleStepSO step) { if (completedSteps.Contains(step)) return; completedSteps.Add(step); Debug.Log($"[Puzzles] Step completed: {step.stepId}"); foreach (var unlock in step.unlocks) { if (AreRuntimeDependenciesMet(unlock)) { Debug.Log($"[Puzzles] Unlocking step {unlock.stepId} after completing {step.stepId}"); UnlockStep(unlock); } else { Debug.Log($"[Puzzles] Step {unlock.stepId} not unlocked yet, waiting for other dependencies"); } } CheckPuzzleCompletion(); } private bool AreRuntimeDependenciesMet(PuzzleStepSO step) { if (!runtimeDependencies.ContainsKey(step) || runtimeDependencies[step].Count == 0) return true; foreach (var dep in runtimeDependencies[step]) { if (!completedSteps.Contains(dep)) return false; } return true; } private void UnlockStep(PuzzleStepSO step) { if (unlockedSteps.Contains(step)) return; unlockedSteps.Add(step); if (stepBehaviours.TryGetValue(step, out var behaviour)) { behaviour.UnlockStep(); } Debug.Log($"[Puzzles] Step unlocked: {step.stepId}"); } private void CheckPuzzleCompletion() { if (completedSteps.Count == stepBehaviours.Count) { Debug.Log("[Puzzles] Puzzle complete! All steps finished."); // TODO: Fire puzzle complete event or trigger outcome logic } } }