diff --git a/Assets/KSH/DungeonTestScene.unity b/Assets/KSH/DungeonTestScene.unity index 5c48dbf7..9351b9ce 100644 --- a/Assets/KSH/DungeonTestScene.unity +++ b/Assets/KSH/DungeonTestScene.unity @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7b994f0db1a78d57442ff714bbde098d085ed1ac985def8e2890bcee787c2d72 -size 236615 +oid sha256:bb988da5d288b7628a63cac1d27c00d9af8c8dd7ca39966efba122a365a2ba50 +size 249093 diff --git a/Assets/LYM/Scripts/ChatWindowController.cs b/Assets/LYM/Scripts/ChatWindowController.cs deleted file mode 100644 index 19eb3f4f..00000000 --- a/Assets/LYM/Scripts/ChatWindowController.cs +++ /dev/null @@ -1,113 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Text; -using TMPro; -using UnityEngine; -using UnityEngine.EventSystems; -using UnityEngine.UI; - -public class ChatWindowController : MonoBehaviour, IPointerClickHandler -{ - [SerializeField] private TMP_Text chatText; - [SerializeField] private Image clickIndicator; - - private Coroutine _typingCoroutine; - private Coroutine _clickCoroutine; - private string _inputText; - private Queue _inputQueue; - - public delegate void OnComplete(); - public OnComplete onComplete; - - private void Start() - { - Init("마무리", () => - { - Debug.Log("대화 끝."); - }); - ShowText(_inputQueue.Dequeue()); - } - - public void Init(string text, OnComplete onComplete) - { - _inputQueue = new Queue(); - _inputQueue.Enqueue("아 망했어 오늘도 지각이다!!!! 이러면 진짜 해고당할 수도 있어!!!\n어떡하지 큰일이다!!!"); - _inputQueue.Enqueue("톼사하셈 ㅋ"); - _inputQueue.Enqueue("톼사하셈 ㅋ"); - _inputQueue.Enqueue("스킵도 가능 톼사하셈 ㅋ톼사하셈 ㅋ톼사하셈 ㅋ톼사하셈 ㅋ톼사하셈 ㅋ"); - _inputQueue.Enqueue(text); - this.onComplete = onComplete; - } - - //화면에 표시할 텍스트 삽입 함수 - private void ShowText(string text) - { - var clickIndicatorColor = clickIndicator.color; - clickIndicatorColor.a = 1; - clickIndicator.color = clickIndicatorColor; - _inputText = text; - if (_typingCoroutine != null) - { - StopCoroutine(_typingCoroutine); - } - _typingCoroutine = StartCoroutine(TypingEffectCoroutine(_inputText)); - } - - //텍스트 타이핑효과 코루틴 - private IEnumerator TypingEffectCoroutine(string text) - { - StringBuilder strText = new StringBuilder(); - for (int i = 0; i < text.Length; i++) - { - strText.Append(text[i]); - chatText.text = strText.ToString(); - yield return new WaitForSeconds(0.1f); - } - - _clickCoroutine = StartCoroutine(ClickIndicatorCoroutine()); - _typingCoroutine = null; - } - - private IEnumerator ClickIndicatorCoroutine() - { - bool flag = true; - var clickIndicatorColor = clickIndicator.color; - while (true) - { - clickIndicatorColor.a = flag? 0:1; - flag = !flag; - clickIndicator.color = clickIndicatorColor; - yield return new WaitForSeconds(0.5f); - } - } - - //대화창 클릭 시 호출 함수 - public void OnPointerClick(PointerEventData eventData) - { - if (_typingCoroutine != null) - { - StopCoroutine(_typingCoroutine); - _typingCoroutine = null; - chatText.text = _inputText; - _clickCoroutine = StartCoroutine(ClickIndicatorCoroutine()); - } - else - { - if (_clickCoroutine != null) - { - StopCoroutine(_clickCoroutine); - _clickCoroutine = null; - } - if (_inputQueue.Count > 0) - { - ShowText(_inputQueue.Dequeue()); - } - else - { - onComplete?.Invoke(); - } - } - } - -} diff --git a/Assets/Resources/Dialogues.meta b/Assets/Resources/Dialogues.meta new file mode 100644 index 00000000..c6019e09 --- /dev/null +++ b/Assets/Resources/Dialogues.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: feed7c503b7a69549acfe2836b78976e +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Resources/Dialogues/dialogue.json b/Assets/Resources/Dialogues/dialogue.json new file mode 100644 index 00000000..8b3f8577 --- /dev/null +++ b/Assets/Resources/Dialogues/dialogue.json @@ -0,0 +1,158 @@ +{ + "dialogues": [ + { + "id": "fairy_intro_1", + "name": "???", + "text": "일어나라 소년, 아니 청년, ...아니 34세의 회사원... 그대의 도움이 필요하다.", + "nextId": "fairy_intro_2", + "phase": "intro" + }, + { + "id": "fairy_intro_2", + "name": "냉장고 요정", + "text": "나는 냉장고의 요정. \n이 냉장고는 세상을 멸망시킬 던전이 잠들어 있다, 그대가 부디 클리어 해주길 바란다. \n...일주일 안에!", + "nextId": "player_intro_1", + "phase": "intro" + }, + { + "id": "player_intro_1", + "name": "주인공", + "text": "...(어쩐지 감자 마켓 온도가 -99도더니...) 내가 왜", + "nextId": "fairy_intro_3", + "phase": "intro" + }, + { + "id": "fairy_intro_3", + "name": "냉장고 요정", + "text": "안 하면 냉장고 터진다.", + "nextId": "player_intro_2", + "phase": "intro" + }, + { + "id": "player_intro_2", + "name": "주인공", + "text": "안돼! 3만원에 사온 내 비X코프 냉장고가! \n(실제 냉장고 상호명과는 아무 관계 없습니다.)", + "nextId": "fairy_intro_4", + "phase": "intro" + }, + { + "id": "fairy_intro_4", + "name": "냉장고 요정", + "text": "또한 냉장고 폭파로 인한 화재가 발생할 수 있으며, 이는 부주의로 인하였기에 보험 적용에 제한이 있을 수 있습니다.", + "nextId": "player_intro_3", + "phase": "intro" + }, + { + "id": "player_intro_3", + "name": "주인공", + "text": "할 수 밖에 없잖아...!!", + "nextId": "", + "phase": "intro" + }, + { + "id": "fairy_gameplay_1", + "name": "냉장고 요정", + "text": "일주일 후 평판이 3이면 좋은 일이 발생할 지도 몰라", + "nextId": "", + "phase": "gameplay" + }, + { + "id": "fairy_gameplay_2", + "name": "냉장고 요정", + "text": "출근 한 번 안했다고 평판 2씩이나 깎는 회사가 있으려나...", + "nextId": "player_gameplay_2", + "phase": "gameplay" + }, + { + "id": "player_gameplay_2", + "name": "주인공", + "text": "(여기 있다.)", + "nextId": "", + "phase": "gameplay" + }, + { + "id": "fairy_gameplay_3", + "name": "냉장고 요정", + "text": "던전은 총 2스테이지까지 있으며 모두 클리어한다면...", + "nextId": "player_gameplay_3", + "phase": "gameplay" + }, + { + "id": "player_gameplay_3", + "name": "주인공", + "text": "한다면... 설마 부와 명예를?", + "nextId": "fairy_gameplay_4", + "phase": "gameplay" + }, + { + "id": "fairy_gameplay_4", + "name": "냉장고 요정", + "text": "축하의 박수를 쳐줄게~", + "nextId": "", + "phase": "gameplay" + }, + { + "id": "fairy_end_1", + "name": "냉장고 요정", + "text": "일주일이 지났네! 수고했어! 이제 이 비스X프 냉장고는 너의 것이야!", + "nextId": "player_end_1", + "phase": "end" + }, + { + "id": "player_end_1", + "name": "주인공", + "text": "(네 도움이 없었다면 불가능했을 거야. 정말 고마워.) \n아자!!!!!!!!!", + "nextId": "fairy_end_2", + "phase": "end" + }, + { + "id": "fairy_end_2", + "name": "냉장고 요정", + "text": "네 덕분에 이 세계는 다시 평화를 되찾았어.", + "nextId": "player_end_2", + "phase": "end" + }, + { + "id": "player_end_2", + "name": "주인공", + "text": "그래... 이제 넌 어떻게 되는 거지?", + "nextId": "fairy_end_3", + "phase": "end" + }, + { + "id": "fairy_end_3", + "name": "냉장고 요정", + "text": "여기 있지...?", + "nextId": "player_end_3", + "phase": "end" + }, + { + "id": "player_end_3", + "name": "주인공", + "text": "?", + "nextId": "fairy_end_4", + "phase": "end" + }, + { + "id": "fairy_end_4", + "name": "냉장고 요정", + "text": "?", + "nextId": "player_end_4", + "phase": "end" + }, + { + "id": "player_end_4", + "name": "주인공", + "text": "... ?", + "nextId": "fairy_end_5", + "phase": "end" + }, + { + "id": "fairy_end_5", + "name": "냉장고 요정", + "text": "... 엔딩 크레딧 출력!", + "nextId": "", + "phase": "end" + } + ] +} \ No newline at end of file diff --git a/Assets/Resources/Dialogues/dialogue.json.meta b/Assets/Resources/Dialogues/dialogue.json.meta new file mode 100644 index 00000000..a107d2e3 --- /dev/null +++ b/Assets/Resources/Dialogues/dialogue.json.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: cac8b86426d9414c912671dbc2fa7959 +timeCreated: 1745890651 \ No newline at end of file diff --git a/Assets/Scripts/Common/Dialogue.meta b/Assets/Scripts/Common/Dialogue.meta new file mode 100644 index 00000000..3118b1f6 --- /dev/null +++ b/Assets/Scripts/Common/Dialogue.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: cfc4230a3c9c2b24b80574293a72e411 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Common/Dialogue/ChatWindowController.cs b/Assets/Scripts/Common/Dialogue/ChatWindowController.cs new file mode 100644 index 00000000..d1b65c41 --- /dev/null +++ b/Assets/Scripts/Common/Dialogue/ChatWindowController.cs @@ -0,0 +1,250 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using TMPro; +using UnityEngine; +using UnityEngine.EventSystems; +using UnityEngine.UI; +using Random = UnityEngine.Random; + +// 대화 데이터 클래스 +[Serializable] +public class DialogueStruct +{ + public string id; // 대화 고유 ID, 세이브용 + public string name; + public string text; + public string nextId; + public string phase; // 단계 (intro, gameplay, end) +} + +[Serializable] +public class DialogueData // 전체 데이터 클래스 +{ + public DialogueData() + { + dialogues = new List(); + } + + public List dialogues; +} + +public enum GamePhase // 단계별로 출력되는 대화가 달라짐 +{ + Intro, // 인트로 설명문 + Gameplay, // 게임 진행 팁? 등 + End // 엔딩 대화 +} + +public class ChatWindowController : MonoBehaviour, IPointerClickHandler +{ + [SerializeField] private TMP_Text nameText; + [SerializeField] private TMP_Text chatText; + [SerializeField] private Image clickIndicator; + [SerializeField] private GameObject chatWindowObject; // 대화 종료용 + + private Coroutine _typingCoroutine; + private Coroutine _clickCoroutine; + private string _inputText; + private Queue _inputQueue; + + public delegate void OnComplete(); + public OnComplete onComplete; + + private bool _dialogueEnded = false; // 대화 종료 여부 + + private FairyDialogueManager _dialogueManager; + + private void Awake() + { + _inputQueue = new Queue(); + chatWindowObject.SetActive(false); // 일단 비활성화로 시작 + } + + private void Start() + { + // FairyDialogueManager 초기화 + _dialogueManager = new FairyDialogueManager(this); + + // 완료 콜백 설정 + onComplete = () => { + Debug.Log("대화가 완료되었습니다."); + }; + + // 테스트 코드: 인트로 대화 시작 + Debug.Log("인트로 대화 시작"); + _dialogueManager.SetGamePhase(GamePhase.Intro); + + // 테스트 코드: 게임플레이 및 엔딩 대화 테스트를 위한 코루틴 시작 + StartCoroutine(TestDialogueSequence()); + } + + // 테스트 코드 + private IEnumerator TestDialogueSequence() + { + // 인트로 대화가 끝날 시간을 대략적으로 기다림 + yield return new WaitForSeconds(5f); + + // 게임플레이 단계로 전환 + Debug.Log("게임플레이 대화 시작"); + _dialogueManager.SetGamePhase(GamePhase.Gameplay); + _dialogueManager.TalkToFairy(); + + // 3초 후 다른 게임플레이 대화 테스트 + yield return new WaitForSeconds(3f); + _dialogueManager.StartDialogueById("fairy_gameplay_2"); + + // 3초 후 엔딩 대화 테스트 + yield return new WaitForSeconds(3f); + Debug.Log("엔딩 대화 시작"); + _dialogueManager.SetGamePhase(GamePhase.End); + } + + // 대화창 표시 + public void ShowWindow() + { + chatWindowObject.SetActive(true); + _dialogueEnded = false; + + if (_inputQueue.Count > 0) + { + ShowNextDialogue(); + } + } + + // 대화창 숨기기 + public void HideWindow() + { + chatWindowObject.SetActive(false); + onComplete?.Invoke(); // 대화창 중지하며 콜백 호출 + + // 진행 중인 모든 코루틴 중지 + if (_typingCoroutine != null) + { + StopCoroutine(_typingCoroutine); + _typingCoroutine = null; + } + + if (_clickCoroutine != null) + { + StopCoroutine(_clickCoroutine); + _clickCoroutine = null; + } + } + + // 대화 시퀀스 설정 + public void SetDialogueSequence(List sequence) + { + // 기존 큐 초기화 + _inputQueue.Clear(); + _dialogueEnded = false; + + // 새 대화 시퀀스를 큐에 추가 + foreach (DialogueStruct dialog in sequence) + { + _inputQueue.Enqueue(dialog); + } + } + + // 다음 대화 표시 + private void ShowNextDialogue() + { + if (_inputQueue.Count == 0) + { + _dialogueEnded = true; + return; + } + + DialogueStruct dialog = _inputQueue.Dequeue(); + + // 이름 텍스트 업데이트 + if (nameText != null) + { + nameText.text = dialog.name; + } + + // 클릭 인디케이터 활성화 + var clickIndicatorColor = clickIndicator.color; + clickIndicatorColor.a = 1; + clickIndicator.color = clickIndicatorColor; + + _inputText = dialog.text; + + // 이전 타이핑 코루틴 중단 + if (_typingCoroutine != null) + { + StopCoroutine(_typingCoroutine); + } + + // 새 타이핑 코루틴 시작 + _typingCoroutine = StartCoroutine(TypingEffectCoroutine(_inputText)); + } + + //텍스트 타이핑효과 코루틴 + private IEnumerator TypingEffectCoroutine(string text) + { + StringBuilder strText = new StringBuilder(); + for (int i = 0; i < text.Length; i++) + { + strText.Append(text[i]); + chatText.text = strText.ToString(); + yield return new WaitForSeconds(0.05f); + } + + _clickCoroutine = StartCoroutine(ClickIndicatorCoroutine()); + _typingCoroutine = null; + } + + private IEnumerator ClickIndicatorCoroutine() + { + bool flag = true; + var clickIndicatorColor = clickIndicator.color; + while (true) + { + clickIndicatorColor.a = flag? 0:1; + flag = !flag; + clickIndicator.color = clickIndicatorColor; + yield return new WaitForSeconds(0.5f); + } + } + + //대화창 클릭 시 호출 함수 + public void OnPointerClick(PointerEventData eventData) + { + if (_typingCoroutine != null) + { + StopCoroutine(_typingCoroutine); + _typingCoroutine = null; + chatText.text = _inputText; + _clickCoroutine = StartCoroutine(ClickIndicatorCoroutine()); + } + else + { + if (_clickCoroutine != null) + { + StopCoroutine(_clickCoroutine); + _clickCoroutine = null; + } + + // 대화가 끝났으면 창 닫기 + if (_dialogueEnded) + { + HideWindow(); + onComplete?.Invoke(); + return; + } + + if (_inputQueue.Count > 0) // 대화가 남은 경우 + { + ShowNextDialogue(); + } + else + { + _dialogueEnded = true; // 일단 대화창 닫고 이후 콜백 호출 + } + } + } + +} diff --git a/Assets/LYM/Scripts/ChatWindowController.cs.meta b/Assets/Scripts/Common/Dialogue/ChatWindowController.cs.meta similarity index 100% rename from Assets/LYM/Scripts/ChatWindowController.cs.meta rename to Assets/Scripts/Common/Dialogue/ChatWindowController.cs.meta diff --git a/Assets/Scripts/Common/Dialogue/FairyDialogueManager.cs b/Assets/Scripts/Common/Dialogue/FairyDialogueManager.cs new file mode 100644 index 00000000..64c3a48d --- /dev/null +++ b/Assets/Scripts/Common/Dialogue/FairyDialogueManager.cs @@ -0,0 +1,255 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using UnityEngine; +using Random = UnityEngine.Random; + +// 일반 클래스로 변경된 FairyDialogueManager +public class FairyDialogueManager +{ + private ChatWindowController _chatWindow; + private string _dialogueFileName; + + // 현재 게임 단계 + private GamePhase _currentGamePhase = GamePhase.Intro; + + private DialogueData _database; + private Dictionary _dialogueDict; + + // 단계별 대화 모음 + private Dictionary> _phaseDialogues; + + // 이미 보여준 게임플레이 대화 추적 + private HashSet _shownGameplayDialogueIds; + + // 생성자 + public FairyDialogueManager(ChatWindowController chatWindow, string dialogueFileName = "dialogue.json") + { + _chatWindow = chatWindow; + _dialogueFileName = dialogueFileName; + _shownGameplayDialogueIds = new HashSet(); + + LoadDialogueData(); + OrganizeDialogues(); + } + + // 대화 데이터베이스 로드 + private void LoadDialogueData() + { + string filePath = "Dialogues/" + _dialogueFileName.Replace(".json", ""); + TextAsset jsonFile = Resources.Load(filePath); + + if (jsonFile == null) + { + Debug.LogError($"Failed to load dialogue database: {filePath}"); + _database = new DialogueData { dialogues = new List() }; + return; + } + + Debug.Log($"JSON 파일 내용: {jsonFile.text.Substring(0, Mathf.Min(200, jsonFile.text.Length))}..."); // 파일 내용 확인 + + try { + _database = JsonUtility.FromJson(jsonFile.text); + Debug.Log($"대화 항목 수: {_database.dialogues.Count}"); + + // 검증: 각 단계별 대화 항목 수 확인 + Dictionary phaseCount = new Dictionary(); + foreach (var dialogue in _database.dialogues) + { + if (!phaseCount.ContainsKey(dialogue.phase)) + phaseCount[dialogue.phase] = 0; + phaseCount[dialogue.phase]++; + } + + foreach (var phase in phaseCount) + { + Debug.Log($"단계 '{phase.Key}': {phase.Value}개 항목"); + } + + // 대화 사전 초기화 + _dialogueDict = new Dictionary(); + foreach (DialogueStruct entry in _database.dialogues) + { + _dialogueDict[entry.id] = entry; + } + } + catch (Exception e) { + Debug.LogError($"JSON 파싱 오류: {e.Message}"); + _database = new DialogueData { dialogues = new List() }; + } + } + + // 대화를 단계별로 분류 + private void OrganizeDialogues() + { + _phaseDialogues = new Dictionary>(); + + foreach (DialogueStruct entry in _database.dialogues) + { + // 단계별 분류 + if (!_phaseDialogues.ContainsKey(entry.phase)) + { + _phaseDialogues[entry.phase] = new List(); + } + _phaseDialogues[entry.phase].Add(entry); + } + } + + // 게임 단계 설정 + public void SetGamePhase(GamePhase phase) + { + _currentGamePhase = phase; + + // Intro 또는 End 단계로 진입 시 자동으로 해당 대화 시작 + if (phase == GamePhase.Intro) + { + StartPhaseDialogue("intro"); + } + else if (phase == GamePhase.End) + { + StartPhaseDialogue("end"); + } + } + + // 단계별 시작 대화 찾기 및 시작 + private void StartPhaseDialogue(string phaseName) + { + if (!_phaseDialogues.ContainsKey(phaseName) || _phaseDialogues[phaseName].Count == 0) + { + Debug.LogWarning($"No dialogues found for phase: {phaseName}"); + return; + } + + // 해당 단계의 첫 대화 항목 찾기 (요정이 먼저 말하는 대화) + DialogueStruct startEntry = _phaseDialogues[phaseName] + .FirstOrDefault(d => d.name == "냉장고 요정" && !string.IsNullOrEmpty(d.nextId)); + + if (startEntry == null) + { + // 적합한 시작 대화가 없으면 첫 번째 대화 사용 + startEntry = _phaseDialogues[phaseName][0]; + } + + // 대화 시퀀스 시작 + StartDialogueSequence(startEntry.id); + } + + // 랜덤 게임플레이 대화 보여주기 + public void ShowRandomGameplayDialogue() + { + if (_currentGamePhase != GamePhase.Gameplay) + { + Debug.LogWarning("Random dialogue can only be shown during gameplay phase"); + return; + } + + // 게임플레이 단계의 요정 대화 중 아직 보여주지 않은 것 찾기 + var availableDialogues = _phaseDialogues["gameplay"] + .Where(d => d.name == "냉장고 요정" && !_shownGameplayDialogueIds.Contains(d.id)) + .ToList(); + + // 모든 대화를 다 보여줬다면 다시 초기화 + if (availableDialogues.Count == 0) + { + _shownGameplayDialogueIds.Clear(); + availableDialogues = _phaseDialogues["gameplay"] + .Where(d => d.name == "냉장고 요정") + .ToList(); + } + + // 랜덤 대화 선택 + if (availableDialogues.Count > 0) + { + int randomIndex = Random.Range(0, availableDialogues.Count); + DialogueStruct randomDialogue = availableDialogues[randomIndex]; + + // 보여준 대화 기록 + _shownGameplayDialogueIds.Add(randomDialogue.id); + + // 대화 시퀀스 시작 + StartDialogueSequence(randomDialogue.id); + } + } + + // 대화 ID로 대화 시작 + public void StartDialogueSequence(string startDialogueId) + { + if (!_dialogueDict.ContainsKey(startDialogueId)) + { + Debug.LogError($"Dialogue ID not found: {startDialogueId}"); + return; + } + + // 시작 대화 항목 가져오기 + DialogueStruct startEntry = _dialogueDict[startDialogueId]; + + // 대화 시퀀스 구성 + List sequence = BuildDialogueSequence(startEntry); + + // 대화창에 대화 시퀀스 전달 + _chatWindow.SetDialogueSequence(sequence); + _chatWindow.ShowWindow(); + } + + // 연결된 대화 시퀀스 구성 + private List BuildDialogueSequence(DialogueStruct startEntry) + { + List sequence = new List(); + HashSet visitedIds = new HashSet(); // 순환 참조 방지 + + DialogueStruct currentEntry = startEntry; + while (currentEntry != null && !visitedIds.Contains(currentEntry.id)) + { + sequence.Add(currentEntry); + visitedIds.Add(currentEntry.id); + + // 다음 대화가 없으면 종료 + if (string.IsNullOrEmpty(currentEntry.nextId) || + !_dialogueDict.ContainsKey(currentEntry.nextId)) + { + break; + } + + // 다음 대화로 이동 + currentEntry = _dialogueDict[currentEntry.nextId]; + } + + return sequence; + } + + // 요정에게 말 걸기 (게임 중 언제든 사용 가능) + public void TalkToFairy() + { + switch (_currentGamePhase) + { + case GamePhase.Intro: + StartPhaseDialogue("intro"); + break; + case GamePhase.Gameplay: + ShowRandomGameplayDialogue(); + break; + case GamePhase.End: + StartPhaseDialogue("end"); + break; + } + } + + // 특정 대화 ID로 대화 시작 (외부에서 호출 가능) + public void StartDialogueById(string dialogueId) + { + if (_dialogueDict.ContainsKey(dialogueId)) + { + StartDialogueSequence(dialogueId); + } + else + { + Debug.LogError($"Dialogue ID not found: {dialogueId}"); + } + } + + // 완료 콜백 설정 + public void SetOnCompleteCallback(ChatWindowController.OnComplete callback) + { + _chatWindow.onComplete = callback; + } +} \ No newline at end of file diff --git a/Assets/Scripts/Common/Dialogue/FairyDialogueManager.cs.meta b/Assets/Scripts/Common/Dialogue/FairyDialogueManager.cs.meta new file mode 100644 index 00000000..0195c799 --- /dev/null +++ b/Assets/Scripts/Common/Dialogue/FairyDialogueManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 5c08c5a9419d39e40b838ea04b98e85e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: