유니티 npc 대사 기능 추가

This commit is contained in:
김민구
2026-07-06 20:05:39 +09:00
parent c06677da25
commit d678ca4f17
2 changed files with 125 additions and 0 deletions
@@ -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<DialogueResponse>(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<Player>();
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;
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 54bd8c582d74a4acb98b5079c1388930