Files
WhaleAdventure_VR/Assets/My project/Dialogue Scripts/UI/DialogueManager.cs
skrwns304@gmail.com b1e85a5b89 2026-06-19 UI, UI로직
2026-06-19 14:27:40 +09:00

272 lines
6.4 KiB
C#

using UnityEngine;
public class DialogueManager : MonoBehaviour
{
[Header("References")]
[SerializeField] private DialogueUI ui;
[SerializeField] private DialogueBillboard billboard;
[Header("Starting Dialogue")]
[SerializeField] private DialogueData startingDialogue;
[SerializeField] private Transform startingTarget;
[SerializeField] private bool startOnAwake = false;
[Header("Settings")]
[SerializeField] private bool allowRestartWhileOpen = true;
[SerializeField] private bool showDebugLog = true;
private DialogueData currentDialogue;
private int currentNodeIndex = -1;
private Transform currentNpcTarget;
public bool IsDialogueActive { get; private set; }
private void Awake()
{
AutoFindReferences();
ValidateReferences();
}
private void Start()
{
if (ui != null)
{
ui.SetVisible(false);
ui.ClearChoices();
}
if (startOnAwake && startingDialogue != null)
StartDialogue(startingDialogue, startingTarget);
}
private void AutoFindReferences()
{
if (ui == null)
ui = FindFirstObjectByType<DialogueUI>();
if (billboard == null)
billboard = FindFirstObjectByType<DialogueBillboard>();
}
private void ValidateReferences()
{
if (ui == null)
Debug.LogWarning("[DialogueManager] DialogueUI가 연결되지 않았습니다.");
if (billboard == null)
Debug.LogWarning("[DialogueManager] DialogueBillboard가 연결되지 않았습니다. VR 위치 추적 기능은 동작하지 않습니다.");
}
public void StartDialogue(DialogueData dialogue)
{
StartDialogue(dialogue, currentNpcTarget);
}
public void StartDialogue(DialogueData dialogue, Transform npc)
{
if (dialogue == null)
{
Debug.LogWarning("[DialogueManager] 시작할 DialogueData가 null입니다.");
return;
}
if (!allowRestartWhileOpen && IsDialogueActive)
return;
if (!dialogue.HasNodes)
{
Debug.LogWarning($"[DialogueManager] DialogueData '{dialogue.name}'에 노드가 없습니다.");
EndDialogue();
return;
}
currentDialogue = dialogue;
currentNodeIndex = 0;
currentNpcTarget = npc;
IsDialogueActive = true;
if (ui != null)
ui.SetVisible(true);
if (billboard != null)
billboard.SetTarget(npc);
ShowCurrentNode();
if (showDebugLog)
Debug.Log($"[DialogueManager] Dialogue Start: {dialogue.name}");
}
public void StartDialogueFromNPC(DialogueData dialogue, Transform npc)
{
StartDialogue(dialogue, npc);
}
public void NextDialogue()
{
if (!IsDialogueActive)
return;
GoToNodeIndex(currentNodeIndex + 1);
}
public void GoToNodeIndex(int index)
{
if (currentDialogue == null)
{
EndDialogue();
return;
}
if (!currentDialogue.IsValidIndex(index))
{
EndDialogue();
return;
}
currentNodeIndex = index;
ShowCurrentNode();
}
public void GoToNodeId(string nodeId)
{
if (currentDialogue == null)
{
EndDialogue();
return;
}
int index = currentDialogue.GetNodeIndexById(nodeId);
if (index < 0)
{
Debug.LogWarning($"[DialogueManager] nodeId '{nodeId}'를 찾을 수 없습니다.");
EndDialogue();
return;
}
GoToNodeIndex(index);
}
private void ShowCurrentNode()
{
if (currentDialogue == null)
{
EndDialogue();
return;
}
if (!currentDialogue.TryGetNode(currentNodeIndex, out DialogueNode node))
{
Debug.LogWarning("[DialogueManager] 현재 노드를 가져올 수 없습니다.");
EndDialogue();
return;
}
if (ui == null)
return;
ui.SetSpeaker(node.speaker);
ui.SetDialogueText(node.dialogue);
if (HasChoices(node))
{
ui.SetNextButtonVisible(false);
ui.CreateChoices(node.choices, OnChoiceClicked);
}
else
{
ui.ClearChoices();
ui.SetNextButtonVisible(true);
ui.SetupNextButton(NextDialogue);
}
}
private bool HasChoices(DialogueNode node)
{
return node != null &&
node.choices != null &&
node.choices.Length > 0;
}
private void OnChoiceClicked(int choiceIndex)
{
if (!IsDialogueActive)
return;
if (currentDialogue == null)
return;
if (!currentDialogue.TryGetNode(currentNodeIndex, out DialogueNode node))
return;
if (node.choices == null ||
choiceIndex < 0 ||
choiceIndex >= node.choices.Length)
return;
ChoiceData choice = node.choices[choiceIndex];
if (choice == null)
return;
HandleChoice(choice);
}
private void HandleChoice(ChoiceData choice)
{
choice.onSelected?.Invoke();
if (choice.endDialogue)
{
EndDialogue();
return;
}
if (choice.nextDialogue != null)
{
StartDialogue(choice.nextDialogue, currentNpcTarget);
return;
}
if (!string.IsNullOrWhiteSpace(choice.nextNodeId))
{
GoToNodeId(choice.nextNodeId);
return;
}
if (choice.nextNodeIndex >= 0)
{
GoToNodeIndex(choice.nextNodeIndex);
return;
}
NextDialogue();
}
public void EndDialogue()
{
if (ui != null)
{
ui.ClearChoices();
ui.SetNextButtonVisible(false);
ui.SetVisible(false);
}
if (billboard != null)
billboard.ClearTarget();
currentDialogue = null;
currentNodeIndex = -1;
currentNpcTarget = null;
IsDialogueActive = false;
if (showDebugLog)
Debug.Log("[DialogueManager] Dialogue End");
}
public void CloseDialogue()
{
EndDialogue();
}
}