Files
Project-AI-Chronicle/unity-client/Assets/Scripts/NPCDialogueManager.cs
T

152 lines
5.2 KiB
C#

using System.Collections;
using UnityEngine;
using UnityEngine.Networking;
public class NPCDialogueManager : MonoBehaviour
{
[Header("UI 연결")]
public GameObject dialoguePanel; // 대화창 배경 패널
public TMPro.TextMeshProUGUI dialogueText; // 대사 텍스트 TMP 컴포넌트
private string lastDialogueText = "대화 버튼을 눌러 조언을 얻으세요.";
private string targetDialogueText = ""; // 목표 대사 텍스트
private Coroutine typingCoroutine; // 타이핑 코루틴 제어용
// JSON 파싱용 Dialogue 응답 매핑 클래스 (스코프 오류 방지를 위해 내부 클래스로 내장)
[System.Serializable]
public class DialogueResponse
{
public string dialogue;
}
private void Start()
{
// 시작 시 대화 패널을 비활성화해 둡니다.
if (dialoguePanel != null)
{
dialoguePanel.SetActive(false);
}
}
// NPC 대화를 요청하는 메서드
public void RequestNPCDialogue(int currentGeneration)
{
StartCoroutine(FetchNPCDialogue(currentGeneration));
}
// NPC 영역을 벗어났을 때 대화창을 명시적으로 닫는 메서드
public void CloseDialogue()
{
if (typingCoroutine != null)
{
StopCoroutine(typingCoroutine);
typingCoroutine = null;
}
if (dialoguePanel != null)
{
dialoguePanel.SetActive(false); // 대화 배경 끄기
}
}
private IEnumerator FetchNPCDialogue(int currentGeneration)
{
// 1. 대화 패널 활성화 및 대기 연출 문구 노출
if (dialoguePanel != null)
{
dialoguePanel.SetActive(true);
}
if (typingCoroutine != null)
{
StopCoroutine(typingCoroutine);
}
lastDialogueText = "늙은 문지기 발두르가 눈을 지그시 감고 네 선조들의 최후를 떠올리는 중입니다...";
if (dialogueText != null)
{
dialogueText.text = lastDialogueText;
}
// FastAPI의 NPC 대화 조회 엔드포인트 URL 구성
string url = $"http://192.168.1.7: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 = "문지기 발두르가 침묵하고 있습니다. (서버 연결 실패)";
if (dialogueText != null)
{
dialogueText.text = 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 = "문지기의 말을 이해할 수 없습니다. (데이터 파싱 오류)";
if (dialogueText != null)
{
dialogueText.text = lastDialogueText;
}
}
}
}
}
// 한 글자씩 부드럽게 출력해주는 타자기 효과 코루틴
private IEnumerator TypeTextEffect(string fullText)
{
lastDialogueText = "";
float letterDelay = 0.04f;
foreach (char letter in fullText.ToCharArray())
{
lastDialogueText += letter;
// 텍스트 UI 컴포넌트 갱신
if (dialogueText != null)
{
dialogueText.text = lastDialogueText;
}
// 공백 문자가 아닌 경우에만 츤데레 훈수 타자기 효과음 재생
if (letter != ' ' && SoundManager.Instance != null)
{
SoundManager.Instance.PlayTyping();
}
// 쉼표(,)나 마침표(.) 등 문장이 끊기는 지점에서는 살짝 더 더듬는 효과(딜레이 추가) 제공
if (letter == ',' || letter == '.')
{
yield return new WaitForSeconds(letterDelay * 4f);
}
else
{
yield return new WaitForSeconds(letterDelay);
}
}
typingCoroutine = null;
}
}