# Conflicts:
#	Assets/TextMesh Pro/Resources/Fonts & Materials/LiberationSans SDF - Fallback.asset
#	Assets/XR/Settings/OpenXRPackageSettings.asset
This commit is contained in:
dldydtn9755-crypto
2026-07-07 18:12:25 +09:00
14 changed files with 555 additions and 27 deletions

View File

@@ -1,6 +0,0 @@
{
"version": "1.0",
"components": [
"Microsoft.VisualStudio.Workload.ManagedGame"
]
}

Binary file not shown.

View File

@@ -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)

View File

@@ -13,7 +13,16 @@ public class ChoiceHud : MonoBehaviour
[SerializeField] private GameObject _root;
[SerializeField] private Transform _rowContainer;
[SerializeField] private DialogChoiceRow _rowPrefab;
[SerializeField] private GameObject _dialogSelectPanelObj;
[SerializeField] private TMP_Text ChoiceQuestion;
[SerializeField] private RectTransform _ScrollRect;
[Header("Layout")]
[Tooltip("선택지 한 줄의 높이")]
[SerializeField] private float _rowHeight = 40f;
[Tooltip("이 줄 수까지만 높이를 늘리고, 넘어가면 스크롤로 본다")]
[SerializeField] private int _maxVisibleRows = 3;
private readonly List<DialogChoiceRow> _rows = new();
private AwaitableCompletionSource<int> _completion;
@@ -51,6 +60,7 @@ public async Awaitable<int> Show(string choiceQuestion, List<DialogChoice> choic
row.OnClicked += HandleClicked;
_rows.Add(row);
}
ResizeToRowCount(choices.Count);
_root.SetActive(true);
_completion = new AwaitableCompletionSource<int>();
@@ -73,6 +83,15 @@ private void HandleClicked(int index)
_completion?.TrySetResult(index);
}
// 선택지 개수에 맞춰 스크롤 영역 높이 조절 (1개=40, 2개=80, 3개=120 …).
// _maxVisibleRows를 넘는 개수는 높이를 더 늘리지 않고 스크롤로 본다.
private void ResizeToRowCount(int count)
{
if (_ScrollRect == null) return;
int visibleRows = Mathf.Min(count, _maxVisibleRows);
_ScrollRect.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, visibleRows * _rowHeight);
}
private void Hide()
{
SetQuestion(null);

View File

@@ -0,0 +1,432 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &1
MonoBehaviour:
m_ObjectHideFlags: 61
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 12501, guid: 0000000000000000e000000000000000, type: 0}
m_Name: Carnotaurus_Dialog2
m_EditorClassIdentifier: UnityEditor.dll::Unity.GraphToolkit.Editor.Implementation.GraphObjectImp
m_GraphModel:
rid: 4848514365209968918
references:
version: 2
RefIds:
- rid: -2
type: {class: , ns: , asm: }
- rid: 4848514365209968918
type: {class: GraphModelImp, ns: Unity.GraphToolkit.Editor.Implementation, asm: UnityEditor.GraphToolkitModule}
data:
m_Guid:
m_Value0: 14743801598135559126
m_Value1: 14874423988134968649
m_HashGuid:
serializedVersion: 2
Hash: d6e3b4ff6f819ccc497d5523cf916cce
m_Name: Carnotaurus_Dialog2
m_GraphNodeModels:
- rid: 4848514365209968921
- rid: 4848514365209968923
- rid: 4848514365209968938
m_GraphWireModels:
- rid: 4848514365209968937
- rid: 4848514365209968939
m_GraphStickyNoteModels: []
m_GraphPlacematModels: []
m_GraphVariableModels: []
m_GraphPortalModels: []
m_SectionModels:
- rid: 4848514365209968919
m_LocalSubgraphs: []
m_LastKnownBounds:
serializedVersion: 2
x: -86
y: 92
width: 1095
height: 432
m_GraphElementMetaData:
- m_Guid:
m_Value0: 11886921906498108818
m_Value1: 1241276629292152157
m_HashGuid:
serializedVersion: 2
Hash: 92fda08d7ed4f6a45df5f38c84e63911
m_Category: 0
m_Index: 0
- m_Guid:
m_Value0: 5760401696664917696
m_Value1: 5304284838533059046
m_HashGuid:
serializedVersion: 2
Hash: c01645bdd20ef14fe6d14014f59a9c49
m_Category: 0
m_Index: 1
- m_Guid:
m_Value0: 12075701744894930101
m_Value1: 8354277098249585595
m_HashGuid:
serializedVersion: 2
Hash: b5ec06d6c18295a7bb03590cc25af073
m_Category: 2
m_Index: 0
- m_Guid:
m_Value0: 18033278169514442201
m_Value1: 7595949161354533057
m_HashGuid:
serializedVersion: 2
Hash: d9fdb665f31243fac1987666843b6a69
m_Category: 0
m_Index: 2
- m_Guid:
m_Value0: 1372665982324540530
m_Value1: 4413923243976307164
m_HashGuid:
serializedVersion: 2
Hash: 7284b72f70b00c13dc310cefcd67413d
m_Category: 2
m_Index: 1
m_EntryPoint:
rid: 4848514365209968921
m_Graph:
rid: 4848514365209968920
- rid: 4848514365209968919
type: {class: SectionModel, ns: Unity.GraphToolkit.Editor, asm: UnityEditor.GraphToolkitModule}
data:
m_Guid:
m_Value0: 17677551595292556901
m_Value1: 13576497333533336155
m_HashGuid:
serializedVersion: 2
Hash: 657e0d28844753f55be24abb646869bc
m_Version: 2
m_Items: []
m_Title:
- rid: 4848514365209968920
type: {class: DialogGraph, ns: DinoLove.Dialog.GraphTool.Editor, asm: Assembly-CSharp-Editor}
data:
- rid: 4848514365209968921
type: {class: UserNodeModelImp, ns: Unity.GraphToolkit.Editor.Implementation, asm: UnityEditor.GraphToolkitModule}
data:
m_Guid:
m_Value0: 11886921906498108818
m_Value1: 1241276629292152157
m_HashGuid:
serializedVersion: 2
Hash: 92fda08d7ed4f6a45df5f38c84e63911
m_Version: 2
m_Position: {x: -86.250015, y: 147.20003}
m_Title:
m_Tooltip:
m_NodePreviewModel:
rid: -2
m_State: 0
m_InputConstantsById:
m_KeyList: []
m_ValueList: []
m_InputPortInfos:
expandedPortsById:
m_KeyList: []
m_ValueList:
m_OutputPortInfos:
expandedPortsById:
m_KeyList: []
m_ValueList:
m_Collapsed: 0
m_CurrentModeIndex: 0
m_ElementColor:
m_Color: {r: 0, g: 0, b: 0, a: 0}
m_HasUserColor: 0
m_Node:
rid: 4848514365209968922
- rid: 4848514365209968922
type: {class: DialogStartNode, ns: DinoLove.Dialog.GraphTool.Editor, asm: Assembly-CSharp-Editor}
data:
- rid: 4848514365209968923
type: {class: UserNodeModelImp, ns: Unity.GraphToolkit.Editor.Implementation, asm: UnityEditor.GraphToolkitModule}
data:
m_Guid:
m_Value0: 5760401696664917696
m_Value1: 5304284838533059046
m_HashGuid:
serializedVersion: 2
Hash: c01645bdd20ef14fe6d14014f59a9c49
m_Version: 2
m_Position: {x: 180.505, y: 92.442505}
m_Title:
m_Tooltip:
m_NodePreviewModel:
rid: -2
m_State: 0
m_InputConstantsById:
m_KeyList:
- __option_ChoiceCount
- __option_EventKey
- Speaker
- TalkText
- Gesture
- Expression
- Voice
- Bgm
- Vfx
- LineDuration
- LookAtPlayer
- WaitForInput
m_ValueList:
- rid: 4848514365209968924
- rid: 4848514365209968925
- rid: 4848514365209968926
- rid: 4848514365209968927
- rid: 4848514365209968928
- rid: 4848514365209968929
- rid: 4848514365209968930
- rid: 4848514365209968931
- rid: 4848514365209968932
- rid: 4848514365209968933
- rid: 4848514365209968934
- rid: 4848514365209968935
m_InputPortInfos:
expandedPortsById:
m_KeyList: []
m_ValueList:
m_OutputPortInfos:
expandedPortsById:
m_KeyList: []
m_ValueList:
m_Collapsed: 0
m_CurrentModeIndex: 0
m_ElementColor:
m_Color: {r: 0, g: 0, b: 0, a: 0}
m_HasUserColor: 0
m_Node:
rid: 4848514365209968936
- rid: 4848514365209968924
type: {class: 'Constant`1[[System.Int32, mscorlib]]', ns: Unity.GraphToolkit.Editor, asm: UnityEditor.GraphToolkitModule}
data:
m_Value: 0
- rid: 4848514365209968925
type: {class: 'Constant`1[[System.String, mscorlib]]', ns: Unity.GraphToolkit.Editor, asm: UnityEditor.GraphToolkitModule}
data:
m_Value:
- rid: 4848514365209968926
type: {class: 'Constant`1[[CharacterData, Assembly-CSharp]]', ns: Unity.GraphToolkit.Editor, asm: UnityEditor.GraphToolkitModule}
data:
m_Value: {fileID: 11400000, guid: b7c3c52c4e4e9fc49bf084eae180835b, type: 2}
- rid: 4848514365209968927
type: {class: 'Constant`1[[DinoLove.Dialog.GraphTool.Editor.DialogText, Assembly-CSharp-Editor]]', ns: Unity.GraphToolkit.Editor, asm: UnityEditor.GraphToolkitModule}
data:
m_Value:
Value: "\uC774\uAC83\uC740 \uB450\uBC88\uC9F8 \uB300\uD654."
- rid: 4848514365209968928
type: {class: 'Constant`1[[GestureData, Assembly-CSharp]]', ns: Unity.GraphToolkit.Editor, asm: UnityEditor.GraphToolkitModule}
data:
m_Value: {fileID: 0}
- rid: 4848514365209968929
type: {class: 'Constant`1[[ExpressionData, Assembly-CSharp]]', ns: Unity.GraphToolkit.Editor, asm: UnityEditor.GraphToolkitModule}
data:
m_Value: {fileID: 0}
- rid: 4848514365209968930
type: {class: 'Constant`1[[VoiceClip, Assembly-CSharp]]', ns: Unity.GraphToolkit.Editor, asm: UnityEditor.GraphToolkitModule}
data:
m_Value: {fileID: 0}
- rid: 4848514365209968931
type: {class: 'Constant`1[[UnityEngine.AudioClip, UnityEngine.AudioModule]]', ns: Unity.GraphToolkit.Editor, asm: UnityEditor.GraphToolkitModule}
data:
m_Value: {fileID: 0}
- rid: 4848514365209968932
type: {class: 'Constant`1[[UnityEngine.GameObject, UnityEngine.CoreModule]]', ns: Unity.GraphToolkit.Editor, asm: UnityEditor.GraphToolkitModule}
data:
m_Value: {fileID: 0}
- rid: 4848514365209968933
type: {class: 'Constant`1[[System.Single, mscorlib]]', ns: Unity.GraphToolkit.Editor, asm: UnityEditor.GraphToolkitModule}
data:
m_Value: 5
- rid: 4848514365209968934
type: {class: 'Constant`1[[System.Boolean, mscorlib]]', ns: Unity.GraphToolkit.Editor, asm: UnityEditor.GraphToolkitModule}
data:
m_Value: 1
- rid: 4848514365209968935
type: {class: 'Constant`1[[System.Boolean, mscorlib]]', ns: Unity.GraphToolkit.Editor, asm: UnityEditor.GraphToolkitModule}
data:
m_Value: 0
- rid: 4848514365209968936
type: {class: DialogLineNode, ns: DinoLove.Dialog.GraphTool.Editor, asm: Assembly-CSharp-Editor}
data:
- rid: 4848514365209968937
type: {class: WireModel, ns: Unity.GraphToolkit.Editor, asm: UnityEditor.GraphToolkitModule}
data:
m_Guid:
m_Value0: 12075701744894930101
m_Value1: 8354277098249585595
m_HashGuid:
serializedVersion: 2
Hash: b5ec06d6c18295a7bb03590cc25af073
m_Version: 2
m_FromPortReference:
m_NodeModelGuid:
m_Value0: 11886921906498108818
m_Value1: 1241276629292152157
m_NodeModelHashGuid:
serializedVersion: 2
Hash: 92fda08d7ed4f6a45df5f38c84e63911
m_UniqueId: Out
m_PortDirection: 2
m_PortOrientation: 0
m_Title:
m_ToPortReference:
m_NodeModelGuid:
m_Value0: 5760401696664917696
m_Value1: 5304284838533059046
m_NodeModelHashGuid:
serializedVersion: 2
Hash: c01645bdd20ef14fe6d14014f59a9c49
m_UniqueId: In
m_PortDirection: 1
m_PortOrientation: 0
m_Title:
- rid: 4848514365209968938
type: {class: UserNodeModelImp, ns: Unity.GraphToolkit.Editor.Implementation, asm: UnityEditor.GraphToolkitModule}
data:
m_Guid:
m_Value0: 18033278169514442201
m_Value1: 7595949161354533057
m_HashGuid:
serializedVersion: 2
Hash: d9fdb665f31243fac1987666843b6a69
m_Version: 2
m_Position: {x: 617.28503, y: 92}
m_Title:
m_Tooltip:
m_NodePreviewModel:
rid: -2
m_State: 0
m_InputConstantsById:
m_KeyList:
- __option_ChoiceCount
- __option_EventKey
- Speaker
- TalkText
- Gesture
- Expression
- Voice
- Bgm
- Vfx
- LineDuration
- LookAtPlayer
- WaitForInput
m_ValueList:
- rid: 4848514365209968940
- rid: 4848514365209968941
- rid: 4848514365209968942
- rid: 4848514365209968943
- rid: 4848514365209968944
- rid: 4848514365209968945
- rid: 4848514365209968946
- rid: 4848514365209968947
- rid: 4848514365209968948
- rid: 4848514365209968949
- rid: 4848514365209968950
- rid: 4848514365209968951
m_InputPortInfos:
expandedPortsById:
m_KeyList: []
m_ValueList:
m_OutputPortInfos:
expandedPortsById:
m_KeyList: []
m_ValueList:
m_Collapsed: 0
m_CurrentModeIndex: 0
m_ElementColor:
m_Color: {r: 0, g: 0, b: 0, a: 0}
m_HasUserColor: 0
m_Node:
rid: 4848514365209968952
- rid: 4848514365209968939
type: {class: WireModel, ns: Unity.GraphToolkit.Editor, asm: UnityEditor.GraphToolkitModule}
data:
m_Guid:
m_Value0: 1372665982324540530
m_Value1: 4413923243976307164
m_HashGuid:
serializedVersion: 2
Hash: 7284b72f70b00c13dc310cefcd67413d
m_Version: 2
m_FromPortReference:
m_NodeModelGuid:
m_Value0: 5760401696664917696
m_Value1: 5304284838533059046
m_NodeModelHashGuid:
serializedVersion: 2
Hash: c01645bdd20ef14fe6d14014f59a9c49
m_UniqueId: Out
m_PortDirection: 2
m_PortOrientation: 0
m_Title:
m_ToPortReference:
m_NodeModelGuid:
m_Value0: 18033278169514442201
m_Value1: 7595949161354533057
m_NodeModelHashGuid:
serializedVersion: 2
Hash: d9fdb665f31243fac1987666843b6a69
m_UniqueId: In
m_PortDirection: 1
m_PortOrientation: 0
m_Title:
- rid: 4848514365209968940
type: {class: 'Constant`1[[System.Int32, mscorlib]]', ns: Unity.GraphToolkit.Editor, asm: UnityEditor.GraphToolkitModule}
data:
m_Value: 0
- rid: 4848514365209968941
type: {class: 'Constant`1[[System.String, mscorlib]]', ns: Unity.GraphToolkit.Editor, asm: UnityEditor.GraphToolkitModule}
data:
m_Value:
- rid: 4848514365209968942
type: {class: 'Constant`1[[CharacterData, Assembly-CSharp]]', ns: Unity.GraphToolkit.Editor, asm: UnityEditor.GraphToolkitModule}
data:
m_Value: {fileID: 11400000, guid: b7c3c52c4e4e9fc49bf084eae180835b, type: 2}
- rid: 4848514365209968943
type: {class: 'Constant`1[[DinoLove.Dialog.GraphTool.Editor.DialogText, Assembly-CSharp-Editor]]', ns: Unity.GraphToolkit.Editor, asm: UnityEditor.GraphToolkitModule}
data:
m_Value:
Value: "\uB180\uB78D\uC9C0?"
- rid: 4848514365209968944
type: {class: 'Constant`1[[GestureData, Assembly-CSharp]]', ns: Unity.GraphToolkit.Editor, asm: UnityEditor.GraphToolkitModule}
data:
m_Value: {fileID: 0}
- rid: 4848514365209968945
type: {class: 'Constant`1[[ExpressionData, Assembly-CSharp]]', ns: Unity.GraphToolkit.Editor, asm: UnityEditor.GraphToolkitModule}
data:
m_Value: {fileID: 0}
- rid: 4848514365209968946
type: {class: 'Constant`1[[VoiceClip, Assembly-CSharp]]', ns: Unity.GraphToolkit.Editor, asm: UnityEditor.GraphToolkitModule}
data:
m_Value: {fileID: 0}
- rid: 4848514365209968947
type: {class: 'Constant`1[[UnityEngine.AudioClip, UnityEngine.AudioModule]]', ns: Unity.GraphToolkit.Editor, asm: UnityEditor.GraphToolkitModule}
data:
m_Value: {fileID: 0}
- rid: 4848514365209968948
type: {class: 'Constant`1[[UnityEngine.GameObject, UnityEngine.CoreModule]]', ns: Unity.GraphToolkit.Editor, asm: UnityEditor.GraphToolkitModule}
data:
m_Value: {fileID: 0}
- rid: 4848514365209968949
type: {class: 'Constant`1[[System.Single, mscorlib]]', ns: Unity.GraphToolkit.Editor, asm: UnityEditor.GraphToolkitModule}
data:
m_Value: 5
- rid: 4848514365209968950
type: {class: 'Constant`1[[System.Boolean, mscorlib]]', ns: Unity.GraphToolkit.Editor, asm: UnityEditor.GraphToolkitModule}
data:
m_Value: 0
- rid: 4848514365209968951
type: {class: 'Constant`1[[System.Boolean, mscorlib]]', ns: Unity.GraphToolkit.Editor, asm: UnityEditor.GraphToolkitModule}
data:
m_Value: 0
- rid: 4848514365209968952
type: {class: DialogLineNode, ns: DinoLove.Dialog.GraphTool.Editor, asm: Assembly-CSharp-Editor}
data:

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: a30515c1ae6d4414ba823659d8fec80f
ScriptedImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 2
userData:
assetBundleName:
assetBundleVariant:
script: {fileID: 11500000, guid: 2ae5ca89bbed445479d9023586f0c041, type: 3}

Binary file not shown.

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 2beaedbeb265d9843b112ed8ff68287d
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: a420815a479c8334da4ee0cd26cd9f35
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.