타이핑 연출

This commit is contained in:
2026-07-30 11:28:35 +09:00
parent 28f014152c
commit 073567c652
14 changed files with 343 additions and 19 deletions

View File

@@ -20,6 +20,10 @@ public class DialogNode : ScriptableObject
[Header("Presentation")]
public AudioClip Bgm; // 있으면 이 대사부터 전용 BGM 재생, 비어있으면 기본 BGM으로 복귀
[Tooltip("이 대사만의 타이핑 연출(속도·글자색·타이핑 사운드). " +
"비우면 DialogHud의 기본 스타일을 쓴다")]
public TypewriterStyle Typewriter;
[Header("Flow")]
public DialogNode Next; // 선택지 없을 때 자동으로 갈 노드
public List<DialogChoice> Choices; // 있으면 플레이어 선택 대기

View File

@@ -288,9 +288,9 @@ private void CaptureInitialAnimState(Animator anim)
// 반환: true = 대기 도중 히든 제스처가 발동됨(→ HiddenBranch로 분기), false = 평범하게 진행
private async Awaitable<bool> PlayNode(DialogNode node)
{
// DialogHud에 대사 표시 (이름은 노드 오버라이드 우선)
// DialogHud에 대사 표시 (이름은 노드 오버라이드 우선, 타이핑 연출도 노드 지정이 우선)
if (DialogHud.Instance != null)
DialogHud.Instance.Show(node.Speaker, node.TalkText, node.SpeakerNameOverride);
DialogHud.Instance.Show(node.Speaker, node.TalkText, node.SpeakerNameOverride, node.Typewriter);
// 호감도 증감 — 화자 기준, 화자가 비어 있으면 대화 주인 NPC
if (node.Affection != 0)
@@ -467,7 +467,12 @@ private async Awaitable<bool> WaitAdvanceOrDivert()
while (true)
{
if (HiddenBranchResolver.Fired) return true; // 히든 발동 → 히든 분기
if (advance) return false; // 진행 입력 → 평범하게 진행
if (advance)
{
advance = false;
// 타이핑 중이었으면 이 입력은 "전체 표시"에 쓰고 계속 기다린다
if (!TrySkipReveal()) return false; // 이미 다 나옴 → 평범하게 진행
}
if (timeLeft >= 0f)
{
timeLeft -= Time.deltaTime;
@@ -486,7 +491,17 @@ private async Awaitable<bool> WaitAdvanceOrDivert()
}
}
// 대화 진행 입력(OnDialogNext) 한 번을 대기
// 대사가 아직 드러나는 중이면 전체 표시로 건너뛰고 true.
// 이미 다 나와 있으면 false — 그 입력은 다음 노드로 넘어가는 데 쓰인다.
private static bool TrySkipReveal()
{
var hud = DialogHud.Instance;
if (hud == null || !hud.IsRevealing) return false;
hud.SkipReveal();
return true;
}
// 대화 진행 입력(OnDialogNext) 한 번을 대기 (타이핑 중이면 첫 입력은 전체 표시에 쓰인다)
private async Awaitable WaitForAdvanceInput()
{
var im = InputManager.Instance;
@@ -502,8 +517,16 @@ private async Awaitable WaitForAdvanceInput()
im.OnDialogNext_Event += Handler;
try
{
while (!pressed)
while (true)
{
if (pressed)
{
pressed = false;
// 타이핑 중이었으면 이 입력은 "전체 표시"에 쓰고 계속 기다린다
if (!TrySkipReveal()) break; // 이미 다 나옴 → 다음 노드로
}
await Awaitable.NextFrameAsync(destroyCancellationToken);
}
}
catch (OperationCanceledException)
{

View File

@@ -10,7 +10,7 @@ namespace DinoLove.Dialog.GraphTool.Editor
// .dlg 그래프 에셋을 기존 런타임 타입(DialogGroup / DialogNode / DialogChoice)으로 변환한다.
// 생성된 DialogNode들은 서브에셋으로, DialogGroup이 메인 에셋으로 등록된다.
// 따라서 DialogPlayer는 수정 없이 임포트된 .dlg 에셋(= DialogGroup)을 그대로 사용한다.
[ScriptedImporter(16, DialogGraph.AssetExtension)] // 버전 올리면 기존 .dlg 에셋이 재임포트됨
[ScriptedImporter(17, DialogGraph.AssetExtension)] // 버전 올리면 기존 .dlg 에셋이 재임포트됨
internal class DialogGraphImporter : ScriptedImporter
{
public override void OnImportAsset(AssetImportContext ctx)
@@ -117,6 +117,7 @@ public override void OnImportAsset(AssetImportContext ctx)
dn.Expression = GetInputPortValue<ExpressionData>(gn.GetInputPortByName(DialogLineNode.PORT_EXPRESSION));
dn.Voice = GetInputPortValue<VoiceClip>(gn.GetInputPortByName(DialogLineNode.PORT_VOICE));
dn.Bgm = GetInputPortValue<AudioClip>(gn.GetInputPortByName(DialogLineNode.PORT_BGM));
dn.Typewriter = GetInputPortValue<TypewriterStyle>(gn.GetInputPortByName(DialogLineNode.PORT_TYPEWRITER));
dn.Affection = GetInputPortValue<int>(gn.GetInputPortByName(DialogLineNode.PORT_AFFECTION));
dn.Progress = GetInputPortValue<int>(gn.GetInputPortByName(DialogLineNode.PORT_PROGRESS));

View File

@@ -21,6 +21,7 @@ internal class DialogLineNode : DialogGraphNode
public const string PORT_EXPRESSION = "Expression";
public const string PORT_VOICE = "Voice";
public const string PORT_BGM = "Bgm";
public const string PORT_TYPEWRITER = "Typewriter";
public const string PORT_AFFECTION = "Affection";
public const string PORT_PROGRESS = "Progress";
public const string PORT_QUESTION = "ChoiceQuestion";
@@ -69,6 +70,9 @@ protected override void OnDefinePorts(IPortDefinitionContext context)
context.AddInputPort<VoiceClip>(PORT_VOICE).WithDisplayName("Voice").Build();
context.AddInputPort<AudioClip>(PORT_BGM).WithDisplayName("BGM")
.WithTooltip("있으면 이 대사부터 전용 BGM 재생, 비우면 기본 BGM으로 복귀").Build();
context.AddInputPort<TypewriterStyle>(PORT_TYPEWRITER).WithDisplayName("Typewriter")
.WithTooltip("이 대사만의 타이핑 연출(속도·글자색·타이핑 사운드). " +
"비우면 DialogHud의 기본 스타일").Build();
context.AddInputPort<int>(PORT_AFFECTION).WithDisplayName("Affection ±")
.WithTooltip("0이 아니면 이 대사 재생 시 화자(비우면 대화 주인 NPC)의 호감도를 이만큼 증감").Build();
context.AddInputPort<int>(PORT_PROGRESS).WithDisplayName("Progress +")