using System.Collections.Generic; using UnityEngine.InputSystem; using UnityEngine; [RequireComponent(typeof(CharacterVoiceObject))] public class DialogPlayer : MonoBehaviour { [SerializeField] private List _dialogGroups; private Dictionary _dialogGroupMap; private Animator _animator; public bool IsPlaying { get; private set; } private void Awake() { _dialogGroupMap = new Dictionary(); foreach (var g in _dialogGroups) _dialogGroupMap[g.DialogGroupName] = g; _animator = GetComponentInChildren(); } public async Awaitable Play() { if(_dialogGroups.Count > 0) _ = Play(_dialogGroups[0].DialogGroupName); } public async Awaitable Play(string groupName) { if (IsPlaying) return; if (!_dialogGroupMap.TryGetValue(groupName, out var group)) { Debug.LogWarning($"[DialogPlayer] 그룹 없음: {groupName}"); return; } IsPlaying = true; try { var node = group.StartNode; while (node != null) { await PlayNode(node); if (node.Choices != null && node.Choices.Count > 0) { int picked = await WaitForChoice(node); node = node.Choices[picked].DestinationNode; } else { node = node.Next; } } } finally { IsPlaying = false; } Debug.Log("[DialogPlayer] 대화 종료"); } private async Awaitable PlayNode(DialogNode node) { var speakerName = node.Speaker != null ? node.Speaker.Name : "(누구?)"; Debug.Log($"[{speakerName}] {node.TalkText}"); // 보이스 재생 if (node.Voice != null && node.Speaker != null) { var voiceObj = CharacterVoiceObject.Find(node.Speaker); if (voiceObj != null && node.Voice.Clip != null) voiceObj.Play(node.Voice.Clip); } if (node.Gesture != null) _animator.CrossFade(node.Gesture.StateName, node.Gesture.CrossFadeDuration, node.Gesture.AnimationLayer); if (node.Expression != null) _animator.CrossFade(node.Expression.StateName, node.Expression.CrossFadeDuration, node.Expression.AnimationLayer); // 대기 시간 결정 float wait = 0f; if (node.Voice != null && node.Voice.Clip != null) wait = node.Voice.Clip.length; else wait = node.LineDuration; if (wait > 0f) await Awaitable.WaitForSecondsAsync(wait); else await WaitForAdvanceInput(); // 수동 진행 } private async Awaitable WaitForChoice(DialogNode node) { // TODO: 선택지 UI 띄우기. 일단은 첫 번째 선택지 자동 선택 (테스트용) Debug.Log("[DialogPlayer] 선택지 대기 — 일단 0번 자동 선택"); await Awaitable.WaitForSecondsAsync(0.5f); return 0; } private async Awaitable WaitForAdvanceInput() { // TODO: VR 컨트롤러 버튼 입력 대기. 일단은 1초 대기 await Awaitable.WaitForSecondsAsync(1f); } }