2026-06-19 UI, UI로직
This commit is contained in:
272
Assets/My project/Dialogue Scripts/UI/DialogueManager.cs
Normal file
272
Assets/My project/Dialogue Scripts/UI/DialogueManager.cs
Normal file
@@ -0,0 +1,272 @@
|
||||
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();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user