다이얼로그 시스템 수정중
This commit is contained in:
@@ -20,6 +20,9 @@ public struct DialogEntry
|
||||
|
||||
[Tooltip("이 대화를 처음 완료하면 메인 진행도 +N (필수 대화가 아니면 0)")]
|
||||
[Min(0)] public int ProgressOnComplete;
|
||||
|
||||
[Tooltip("대화 선택 메뉴에 표시할 이름 (비우면 그룹 이름 사용)")]
|
||||
public string MenuLabel;
|
||||
}
|
||||
|
||||
// 노드의 EventKey ↔ 그 노드 재생 시 호출할 이벤트.
|
||||
@@ -30,9 +33,12 @@ public struct NodeEvent
|
||||
public UnityEvent Event;
|
||||
}
|
||||
|
||||
[Tooltip("이 NPC의 대화 후보들. 위에서부터 조건을 검사해 첫 번째로 만족하는 대화를 재생")]
|
||||
[Tooltip("이 NPC의 대화 후보들. 조건을 만족하는 대화가 여럿이면 플레이어가 선택한다")]
|
||||
[SerializeField] private List<DialogEntry> _dialogs = new();
|
||||
|
||||
[Tooltip("대화가 여러 개일 때 선택 메뉴 상단에 표시할 안내 문구")]
|
||||
[SerializeField] private string _dialogSelectPrompt = "무슨 이야기를 나눌까?";
|
||||
|
||||
[Header("Dialog HUD Placement")] // 씬에서 캐릭터 위치/주변(벽 등)에 맞춰 조절
|
||||
[SerializeField] private float _hudChestHeight = 1.2f; // 화자 발 기준 가슴 높이
|
||||
[SerializeField] private float _hudForwardOffset = 0.5f; // 화자→플레이어 방향으로 띄울 거리
|
||||
@@ -70,32 +76,79 @@ public async Awaitable Play()
|
||||
{
|
||||
if (IsPlaying) return;
|
||||
|
||||
int index = FindPlayableIndex();
|
||||
if (index < 0)
|
||||
// 선택 메뉴가 떠 있는 동안에도 재진입을 막아야 하므로 여기서 잠근다.
|
||||
IsPlaying = true;
|
||||
try
|
||||
{
|
||||
Debug.Log($"[DialogPlayer] 조건에 맞는 대화가 없음: {name}");
|
||||
return;
|
||||
var playable = FindPlayableIndices();
|
||||
if (playable.Count == 0)
|
||||
{
|
||||
Debug.Log($"[DialogPlayer] 조건에 맞는 대화가 없음: {name}");
|
||||
return;
|
||||
}
|
||||
|
||||
int index = playable.Count == 1 ? playable[0] : await SelectDialog(playable);
|
||||
if (index < 0) return; // 선택 대기 중 취소됨 (씬 전환 등)
|
||||
|
||||
await PlayEntry(_dialogs[index]);
|
||||
}
|
||||
finally
|
||||
{
|
||||
IsPlaying = false;
|
||||
}
|
||||
await PlayEntry(_dialogs[index]);
|
||||
}
|
||||
|
||||
// 리스트 순서 = 우선순위. 조건을 만족하고 (반복 가능하거나 아직 안 한) 첫 대화.
|
||||
private int FindPlayableIndex()
|
||||
// 조건을 만족하고 (반복 가능하거나 아직 안 한) 대화들의 인덱스. 리스트 순서 유지.
|
||||
private List<int> FindPlayableIndices()
|
||||
{
|
||||
var result = new List<int>();
|
||||
for (int i = 0; i < _dialogs.Count; i++)
|
||||
{
|
||||
var entry = _dialogs[i];
|
||||
if (entry.Group == null) continue;
|
||||
if (!entry.Repeatable && StoryManager.Instance.IsDialogCompleted(entry.Group.name)) continue;
|
||||
if (entry.Condition != null && !entry.Condition.IsMet(_voice.Character)) continue;
|
||||
return i;
|
||||
result.Add(i);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// 재생 가능한 대화가 여럿일 때 ChoiceHud로 플레이어에게 고르게 한다. 반환값은 _dialogs 인덱스.
|
||||
private async Awaitable<int> SelectDialog(List<int> playable)
|
||||
{
|
||||
if (ChoiceHud.Instance == null)
|
||||
return playable[0]; // 선택 UI가 없으면 기존처럼 최상단 우선
|
||||
|
||||
// ChoiceHud는 DialogHud를 따라 배치되므로, 먼저 화자 옆에 HUD를 띄운다.
|
||||
if (DialogHud.Instance != null)
|
||||
DialogHud.Instance.Show(_voice.Character, _dialogSelectPrompt, _hudChestHeight, _hudForwardOffset, _hudLateralOffset);
|
||||
|
||||
var options = new List<DialogChoice>(playable.Count);
|
||||
foreach (int i in playable)
|
||||
{
|
||||
var entry = _dialogs[i];
|
||||
string label = !string.IsNullOrWhiteSpace(entry.MenuLabel)
|
||||
? entry.MenuLabel
|
||||
: entry.Group.DialogGroupName;
|
||||
options.Add(new DialogChoice { ChoiceText = label }); // Code 없음 → 선택 이력에 기록 안 됨
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
int picked = await ChoiceHud.Instance.Show(null, options);
|
||||
return playable[picked];
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
// 대기 중 ChoiceHud가 비활성화됨(씬 전환 등) — 재생하지 않음
|
||||
if (DialogHud.Instance != null)
|
||||
DialogHud.Instance.Hide();
|
||||
return -1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
private async Awaitable PlayEntry(DialogEntry entry)
|
||||
{
|
||||
IsPlaying = true;
|
||||
try
|
||||
{
|
||||
var node = entry.Group.StartNode;
|
||||
@@ -127,7 +180,6 @@ private async Awaitable PlayEntry(DialogEntry entry)
|
||||
}
|
||||
finally
|
||||
{
|
||||
IsPlaying = false;
|
||||
if (DialogHud.Instance != null)
|
||||
DialogHud.Instance.Hide();
|
||||
if (SoundManager.Instance != null)
|
||||
|
||||
Reference in New Issue
Block a user