using System.Collections; using System.Collections.Generic; using UnityEngine; public class DialogueManager : MonoBehaviour { public static DialogueManager Instance { get; private set; } [Header("Hook up the UI component here")] public DialogueUI ui; [Header("Flags saved during play (simple global state)")] public HashSet flags = new(); DialogueAsset _active; DialogueAsset.Node _node; int _lineIndex; bool _isTyping; Coroutine _typeRoutine; void Awake() { if (Instance != null && Instance != this) { Destroy(gameObject); return; } Instance = this; DontDestroyOnLoad(gameObject); } // Public API ------------- public bool IsRunning => _active != null; public void StartDialogue(DialogueAsset asset) { if (asset == null) return; _active = asset; GoToNode(asset.startNodeId); ui.Show(true); } public void StopDialogue() { _active = null; _node = null; ui.Show(false); } public void Next() // Called by UI "Continue" button / input { if (!IsRunning || _node == null) return; if (_isTyping) { ui.CompleteTypeThisFrame(); _isTyping = false; return; } // Advance line within node _lineIndex++; if (_lineIndex < _node.lines.Count) { StartTyping(_node.lines[_lineIndex]); } else { // Lines finished -> show choices or auto-next / end var visibleChoices = ui.BuildVisibleChoices(_node.choices, flags); if (visibleChoices.Count > 0) { ui.ShowChoices(visibleChoices, OnChoicePicked); } else { if (_node.nextNodeId >= 0) GoToNode(_node.nextNodeId); else StopDialogue(); } } } // Internal ------------- void GoToNode(int id) { if (!_active.TryGetNode(id, out _node)) { Debug.LogWarning($"Dialogue node {id} not found."); StopDialogue(); return; } _lineIndex = 0; _node.onEnter?.Invoke(); ui.BindSpeaker(_node.speakerName, _node.speakerPortrait); if (_node.lines.Count == 0) { // Empty node: immediately resolve choices/next var visibleChoices = ui.BuildVisibleChoices(_node.choices, flags); if (visibleChoices.Count > 0) ui.ShowChoices(visibleChoices, OnChoicePicked); else if (_node.nextNodeId >= 0) GoToNode(_node.nextNodeId); else StopDialogue(); } else { StartTyping(_node.lines[_lineIndex]); } } void StartTyping(string text) { ui.HideChoices(); if (_typeRoutine != null) StopCoroutine(_typeRoutine); _typeRoutine = StartCoroutine(TypeRoutine(text)); } IEnumerator TypeRoutine(string text) { _isTyping = true; yield return ui.TypeText(text); _isTyping = false; } void OnChoicePicked(DialogueAsset.Choice choice) { choice?.onChoose?.Invoke(); if (!string.IsNullOrEmpty(choice.setFlag)) flags.Add(choice.setFlag); if (choice == null || choice.nextNodeId < 0) { StopDialogue(); return; } GoToNode(choice.nextNodeId); } }