253 lines
6.7 KiB
C#
253 lines
6.7 KiB
C#
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<DialogueStruct>();
|
|
}
|
|
|
|
public List<DialogueStruct> dialogues;
|
|
}
|
|
|
|
public enum GamePhase // 단계별로 출력되는 대화가 달라짐
|
|
{
|
|
Intro, // 인트로 설명문
|
|
Gameplay, // 게임 진행 팁? 등
|
|
End, // 회고 엔딩
|
|
ZeroEnd, // 평판 0 엔딩
|
|
FailEnd // 같은 스테이지 3회 실패 엔딩
|
|
}
|
|
|
|
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<DialogueStruct> _inputQueue;
|
|
|
|
public delegate void OnComplete();
|
|
public OnComplete onComplete;
|
|
private bool isEnded;
|
|
private bool isTuto;
|
|
|
|
private FairyDialogueManager _dialogueManager;
|
|
|
|
private void Awake()
|
|
{
|
|
_inputQueue = new Queue<DialogueStruct>();
|
|
chatWindowObject.SetActive(false); // 일단 비활성화로 시작
|
|
}
|
|
|
|
private void Start()
|
|
{
|
|
isEnded = false;
|
|
isTuto = false;
|
|
|
|
_dialogueManager = new FairyDialogueManager(this);
|
|
|
|
onComplete = () =>
|
|
{
|
|
GameManager.Instance.gotoBed = true;
|
|
};
|
|
|
|
onComplete = () => {
|
|
if (isTuto)
|
|
{
|
|
isTuto = false;
|
|
StartCoroutine(GameManager.Instance.StartTutorialCoroutine());
|
|
}
|
|
|
|
if (isEnded)
|
|
GameManager.Instance.ChangeToMainScene();
|
|
};
|
|
}
|
|
|
|
// 외부 호출용 함수 (대화 시작)
|
|
public void SetGamePhase(GamePhase phase)
|
|
{
|
|
_dialogueManager.SetGamePhase(phase);
|
|
|
|
if (phase == GamePhase.End || phase == GamePhase.FailEnd || phase == GamePhase.ZeroEnd)
|
|
isEnded = true;
|
|
|
|
if (phase == GamePhase.Intro)
|
|
isTuto = true;
|
|
|
|
// Gameplay 상태라면 랜덤 대화 출력
|
|
if (phase == GamePhase.Gameplay) _dialogueManager.ShowRandomGameplayDialogue();
|
|
}
|
|
|
|
#region Show and Hide
|
|
|
|
// 대화창 표시
|
|
public void ShowWindow()
|
|
{
|
|
chatWindowObject.SetActive(true);
|
|
|
|
if (_inputQueue.Count > 0)
|
|
{
|
|
ShowNextDialogue();
|
|
PlayerStats.Instance.HideBubble();
|
|
}
|
|
}
|
|
|
|
// 대화창 숨기기
|
|
public void HideWindow()
|
|
{
|
|
chatWindowObject.SetActive(false);
|
|
onComplete?.Invoke(); // 대화창 중지하며 콜백 호출
|
|
|
|
// 진행 중인 모든 코루틴 중지
|
|
if (_typingCoroutine != null)
|
|
{
|
|
StopCoroutine(_typingCoroutine);
|
|
_typingCoroutine = null;
|
|
}
|
|
|
|
if (_clickCoroutine != null)
|
|
{
|
|
StopCoroutine(_clickCoroutine);
|
|
_clickCoroutine = null;
|
|
}
|
|
|
|
PlayerStats.Instance.ShowBubble();
|
|
}
|
|
|
|
#endregion
|
|
|
|
// 대화 시퀀스 설정
|
|
public void SetDialogueSequence(List<DialogueStruct> sequence)
|
|
{
|
|
// 기존 큐 초기화
|
|
_inputQueue.Clear();
|
|
|
|
// 새 대화 시퀀스를 큐에 추가
|
|
foreach (DialogueStruct dialog in sequence)
|
|
{
|
|
_inputQueue.Enqueue(dialog);
|
|
}
|
|
}
|
|
|
|
// 다음 대화 표시
|
|
private void ShowNextDialogue()
|
|
{
|
|
if (_inputQueue.Count == 0)
|
|
{
|
|
HideWindow();
|
|
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);
|
|
GameManager.Instance.PlayTypingSound();
|
|
}
|
|
|
|
_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 (!chatWindowObject.activeSelf) // 실제론 대화창이 off 상태인데 호출되는 상황 방지
|
|
return;
|
|
|
|
if (_typingCoroutine != null)
|
|
{
|
|
StopCoroutine(_typingCoroutine);
|
|
_typingCoroutine = null;
|
|
if (chatText != null) chatText.text = _inputText;
|
|
if (clickIndicator != null) _clickCoroutine = StartCoroutine(ClickIndicatorCoroutine());
|
|
}
|
|
else
|
|
{
|
|
if (_clickCoroutine != null)
|
|
{
|
|
StopCoroutine(_clickCoroutine);
|
|
_clickCoroutine = null;
|
|
}
|
|
|
|
if (_inputQueue.Count > 0) // 대화가 남은 경우
|
|
{
|
|
ShowNextDialogue();
|
|
}
|
|
else
|
|
{
|
|
HideWindow(); // 대화 종료되면 창 닫기
|
|
}
|
|
}
|
|
}
|
|
}
|