152 lines
5.2 KiB
C#
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;
|
|
}
|
|
|
|
|
|
}
|