3D 잔재 제거
This commit is contained in:
@@ -24,7 +24,7 @@ public class DialogPlayer : MonoBehaviour
|
||||
|
||||
// ── 전역 대화 진행 신호 (대화 중 월드 상호작용 차단용) ────────
|
||||
// 선택 메뉴 단계부터 대사 종료까지, 어느 NPC든 대화가 진행 중이면 true.
|
||||
// DialogInteractionBlocker가 구독해서 인터랙터를 잠근다.
|
||||
// 이동 버튼·클릭 인터랙션 등이 AnyActiveChanged를 구독해 대화 중 입력을 잠그면 된다.
|
||||
public static bool IsAnyActive => _activeCount > 0;
|
||||
public static event Action<bool> AnyActiveChanged;
|
||||
private static int _activeCount;
|
||||
@@ -103,7 +103,7 @@ public async Awaitable Play()
|
||||
}
|
||||
}
|
||||
|
||||
// 조건/선택 메뉴를 건너뛰고 특정 대화 그룹을 강제로 시작한다 (EventZoneTrigger 등 UnityEvent 연결용).
|
||||
// 조건/선택 메뉴를 건너뛰고 특정 대화 그룹을 강제로 시작한다 (버튼·컷신 등 UnityEvent 연결용).
|
||||
// DB에 등록된 비트면 그 설정(진행도 보상 등)을 그대로 쓰고, 없으면 임시 비트로 재생한다.
|
||||
// 완료 여부는 검사하지 않으므로(강제) 1회성이 필요하면 호출하는 쪽(존의 Trigger Once)에서 보장할 것.
|
||||
public void PlayGroup(DialogGroup group)
|
||||
@@ -204,26 +204,24 @@ private async Awaitable PlayBeat(StoryBeat beat)
|
||||
}
|
||||
routingHops = 0; // 실제 대사 노드에 도달 — 카운터 리셋
|
||||
|
||||
// 이 노드가 히든 분기를 가지면, 노드가 재생되는 동안 제스처 감시를 무장한다.
|
||||
// 이 노드가 히든 분기를 가지면, 노드가 재생되는 동안 발동 감시를 무장한다.
|
||||
// (무장 안 된 노드는 아래 대기/선택이 기존과 완전히 동일하게 동작)
|
||||
bool armed = node.HiddenBranch != null;
|
||||
if (armed) HiddenBranchResolver.Arm(node.HiddenGestureKey);
|
||||
bool armed = node.HiddenBranches != null && node.HiddenBranches.Count > 0;
|
||||
if (armed) HiddenBranchResolver.Arm(node.HiddenBranches);
|
||||
try
|
||||
{
|
||||
bool diverted = await PlayNode(node); // 대사 표시 + 대기(무장 시 제스처 감시 포함)
|
||||
bool diverted = await PlayNode(node); // 대사 표시 + 대기(무장 시 발동 감시 포함)
|
||||
|
||||
if (diverted)
|
||||
{
|
||||
RecordHiddenChoice(node);
|
||||
node = node.HiddenBranch; // 대사 도중 제스처 발동 → 몰래 분기
|
||||
node = TakeHiddenBranch(node); // 대사 도중 발동 → 몰래 분기
|
||||
}
|
||||
else if (node.Choices != null && node.Choices.Count > 0)
|
||||
{
|
||||
int picked = await WaitForChoice(node); // 메뉴(무장 시 제스처 감시 포함)
|
||||
int picked = await WaitForChoice(node); // 메뉴(무장 시 발동 감시 포함)
|
||||
if (picked == DivertIndex)
|
||||
{
|
||||
RecordHiddenChoice(node);
|
||||
node = node.HiddenBranch; // 메뉴 도중 제스처 발동 → 메뉴엔 없던 히든 분기
|
||||
node = TakeHiddenBranch(node); // 메뉴 도중 발동 → 메뉴엔 없던 히든 분기
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -341,7 +339,7 @@ private async Awaitable<bool> PlayNode(DialogNode node)
|
||||
}
|
||||
|
||||
// 진행은 항상 플레이어 입력 대기.
|
||||
// 히든 분기가 무장된 노드는 대기 중 제스처를 함께 감시(레이스)한다.
|
||||
// 히든 분기가 무장된 노드는 대기 중 히든 발동을 함께 감시(레이스)한다.
|
||||
if (HiddenBranchResolver.Armed)
|
||||
return await WaitAdvanceOrDivert();
|
||||
|
||||
@@ -393,12 +391,26 @@ private void RecordChoice(DialogNode node, int index)
|
||||
StoryManager.Instance.RecordChoice(code);
|
||||
}
|
||||
|
||||
// 히든 분기 기록: 노드의 HiddenCode를 선택지 Code와 동일하게 StoryState에 영구 기록
|
||||
private void RecordHiddenChoice(DialogNode node)
|
||||
// 발동한 히든 분기로 이동한다. 어느 분기가 발동했는지는 Resolver가 키를 보고 이미 골라 뒀다.
|
||||
// (Disarm보다 먼저 불려야 하므로 반드시 무장 구간 안에서 호출할 것)
|
||||
private DialogNode TakeHiddenBranch(DialogNode node)
|
||||
{
|
||||
string code = DialogVariables.Format(node.HiddenCode); // {token} 치환
|
||||
int index = HiddenBranchResolver.FiredIndex;
|
||||
if (node.HiddenBranches == null || index < 0 || index >= node.HiddenBranches.Count)
|
||||
{
|
||||
// 정상 흐름에선 올 수 없다(발동 = 매칭 성공). 와도 대화가 끊기지 않게 원래 흐름으로.
|
||||
Debug.LogWarning($"[DialogPlayer] 히든 분기 인덱스가 범위를 벗어남: {index}");
|
||||
return node.Next;
|
||||
}
|
||||
|
||||
var branch = node.HiddenBranches[index];
|
||||
|
||||
// 선택지 Code와 동일하게 StoryState에 영구 기록
|
||||
string code = DialogVariables.Format(branch.Code); // {token} 치환
|
||||
if (!string.IsNullOrEmpty(code))
|
||||
StoryManager.Instance.RecordChoice(code);
|
||||
|
||||
return branch.Destination;
|
||||
}
|
||||
|
||||
// 히든 분기 신호값 — 선택지 인덱스(0..n-1)와 절대 겹치지 않는 값.
|
||||
@@ -416,11 +428,11 @@ private async Awaitable<int> WaitForChoice(DialogNode node)
|
||||
if (!HiddenBranchResolver.Armed)
|
||||
return await ChoiceHud.Instance.Show(node.ChoiceQuestion, node.Choices);
|
||||
|
||||
// 무장된 노드: 메뉴가 떠 있는 동안 제스처가 들어오면 메뉴를 취소하고 히든으로 분기.
|
||||
// 무장된 노드: 메뉴가 떠 있는 동안 발동이 들어오면 메뉴를 취소하고 히든으로 분기.
|
||||
if (HiddenBranchResolver.Fired)
|
||||
return DivertIndex; // 메뉴가 뜨기 전에 이미 발동한 경우
|
||||
|
||||
void OnFired() => ChoiceHud.Instance.CancelPending(); // 제스처 → 메뉴 즉시 취소
|
||||
void OnFired() => ChoiceHud.Instance.CancelPending(); // 발동 → 메뉴 즉시 취소
|
||||
HiddenBranchResolver.FiredEvent += OnFired;
|
||||
try
|
||||
{
|
||||
@@ -428,7 +440,7 @@ private async Awaitable<int> WaitForChoice(DialogNode node)
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
// 우리가 제스처로 취소한 것이면 히든 분기, 아니면(씬 전환 등) 위로 전파
|
||||
// 우리가 히든 발동으로 취소한 것이면 히든 분기, 아니면(씬 전환 등) 위로 전파
|
||||
if (HiddenBranchResolver.Fired) return DivertIndex;
|
||||
throw;
|
||||
}
|
||||
@@ -438,8 +450,8 @@ private async Awaitable<int> WaitForChoice(DialogNode node)
|
||||
}
|
||||
}
|
||||
|
||||
// 노드 대기 + 히든 제스처 감시(레이스). 무장된 노드에서만 호출된다.
|
||||
// 반환: true = 대기 도중 제스처 발동(→히든 분기), false = 평범하게 진행(입력)
|
||||
// 노드 대기 + 히든 발동 감시(레이스). 무장된 노드에서만 호출된다.
|
||||
// 반환: true = 대기 도중 히든 발동(→히든 분기), false = 평범하게 진행(입력)
|
||||
private async Awaitable<bool> WaitAdvanceOrDivert()
|
||||
{
|
||||
var im = InputManager.Instance;
|
||||
@@ -454,7 +466,7 @@ private async Awaitable<bool> WaitAdvanceOrDivert()
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
if (HiddenBranchResolver.Fired) return true; // 제스처 발동 → 히든 분기
|
||||
if (HiddenBranchResolver.Fired) return true; // 히든 발동 → 히든 분기
|
||||
if (advance) return false; // 진행 입력 → 평범하게 진행
|
||||
if (timeLeft >= 0f)
|
||||
{
|
||||
@@ -503,15 +515,16 @@ private async Awaitable WaitForAdvanceInput()
|
||||
}
|
||||
}
|
||||
|
||||
//테스트용
|
||||
//테스트용 — 캐릭터를 클릭하면 대화 시작 (Collider2D가 있어야 잡힌다)
|
||||
private void Update()
|
||||
{
|
||||
if (Mouse.current == null) return;
|
||||
if (!Mouse.current.leftButton.wasPressedThisFrame) return;
|
||||
if (Camera.main == null) return;
|
||||
|
||||
var ray = Camera.main.ScreenPointToRay(Mouse.current.position.ReadValue());
|
||||
if (Physics.Raycast(ray, out var hit) && hit.transform.IsChildOf(transform))
|
||||
var world = Camera.main.ScreenToWorldPoint(Mouse.current.position.ReadValue());
|
||||
var hit = Physics2D.OverlapPoint(world);
|
||||
if (hit != null && hit.transform.IsChildOf(transform))
|
||||
{
|
||||
Debug.Log("캐릭터 클릭");
|
||||
_ = Play(); // 테스트용 fire-and-forget (Update는 await 불가)
|
||||
|
||||
Reference in New Issue
Block a user