diff --git a/unity-client/Assets/Scripts/NPCDialogueManager.cs b/unity-client/Assets/Scripts/NPCDialogueManager.cs new file mode 100644 index 0000000..ebe79ed --- /dev/null +++ b/unity-client/Assets/Scripts/NPCDialogueManager.cs @@ -0,0 +1,123 @@ +using System.Collections; +using UnityEngine; +using UnityEngine.Networking; + +public class NPCDialogueManager : MonoBehaviour +{ + private string lastDialogueText = "대화 버튼을 눌러 조언을 얻으세요."; + private string targetDialogueText = ""; // 목표 대사 텍스트 + private Coroutine typingCoroutine; // 타이핑 코루틴 제어용 + + // NPC 대화를 요청하는 메서드 + public void RequestNPCDialogue(int currentGeneration) + { + StartCoroutine(FetchNPCDialogue(currentGeneration)); + } + + private IEnumerator FetchNPCDialogue(int currentGeneration) + { + // 1. 대기 연출: 요청 즉시 로딩중 텍스트를 띄워 렉처럼 보이지 않게 합니다. + if (typingCoroutine != null) + { + StopCoroutine(typingCoroutine); + } + lastDialogueText = "늙은 문지기 발두르가 눈을 지그시 감고 네 선조들의 최후를 떠올리는 중입니다..."; + + // FastAPI의 NPC 대화 조회 엔드포인트 URL 구성 + string url = $"http://127.0.0.1:8000/api/game/npc-dialogue?current_generation={currentGeneration}"; + Debug.Log($"[Dialogue] NPC 대사 조회 요청 전송: {url}"); + + using (UnityWebRequest request = UnityWebRequest.Get(url)) + { + yield return request.SendWebRequest(); + + if (request.result == UnityWebRequest.Result.ConnectionError || + request.result == UnityWebRequest.Result.ProtocolError) + { + Debug.LogError($"[Dialogue] NPC 대사 조회 실패: {request.error}"); + lastDialogueText = "문지기 발두르가 침묵하고 있습니다. (서버 연결 실패)"; + } + else + { + try + { + string json = request.downloadHandler.text; + DialogueResponse response = JsonUtility.FromJson(json); + + targetDialogueText = response.dialogue; + Debug.Log($"[Dialogue] 문지기 대사 수신 성공:\n{targetDialogueText}"); + + // 2. 타자기 연출(Typewriter) 코루틴 시작 + typingCoroutine = StartCoroutine(TypeTextEffect(targetDialogueText)); + } + catch (System.Exception ex) + { + Debug.LogError($"[Dialogue] JSON 파싱 에러: {ex.Message}"); + lastDialogueText = "문지기의 말을 이해할 수 없습니다. (데이터 파싱 오류)"; + } + } + } + } + + // 한 글자씩 부드럽게 출력해주는 타자기 효과 코루틴 + private IEnumerator TypeTextEffect(string fullText) + { + lastDialogueText = ""; + // 문지기가 고민하면서 한 글자씩 읊조리는 속도 (0.04초 간격) + float letterDelay = 0.04f; + + foreach (char letter in fullText.ToCharArray()) + { + lastDialogueText += letter; + + // 쉼표(,)나 마침표(.) 등 문장이 끊기는 지점에서는 살짝 더 더듬는 효과(딜레이 추가) 제공 + if (letter == ',' || letter == '.') + { + yield return new WaitForSeconds(letterDelay * 4f); + } + else + { + yield return new WaitForSeconds(letterDelay); + } + } + typingCoroutine = null; + } + + // 디버그용 임시 GUI 버튼 및 대사 출력창 + private void OnGUI() + { + GUI.backgroundColor = Color.yellow; + + // NPC 대화 요청 버튼 (화면 우측 상단 배치) + if (GUI.Button(new Rect(Screen.width - 240, 10, 220, 50), "Debug: Get NPC Dialogue")) + { + // 플레이어 오브젝트를 찾아 현재 세대 값을 가져옵니다. + Player player = FindObjectOfType(); + if (player != null) + { + RequestNPCDialogue(player.Generation); + } + else + { + RequestNPCDialogue(1); + } + } + + // 대사 출력 박스 배경 및 텍스트 렌더링 + GUI.color = Color.white; + GUI.Box(new Rect(Screen.width - 450, 70, 430, 120), "늙은 문지기 '발두르'의 조언"); + + GUIStyle dialogueStyle = new GUIStyle(GUI.skin.label); + dialogueStyle.wordWrap = true; + dialogueStyle.fontSize = 14; + + GUI.Label(new Rect(Screen.width - 440, 95, 410, 90), lastDialogueText, dialogueStyle); + } +} + +// JSON 파싱용 Dialogue 응답 매핑 클래스 +[System.Serializable] +public class DialogueResponse +{ + public string dialogue; +} diff --git a/unity-client/Assets/Scripts/NPCDialogueManager.cs.meta b/unity-client/Assets/Scripts/NPCDialogueManager.cs.meta new file mode 100644 index 0000000..49949ad --- /dev/null +++ b/unity-client/Assets/Scripts/NPCDialogueManager.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 54bd8c582d74a4acb98b5079c1388930 \ No newline at end of file