
CSV를 이용한 대화 기능 구현

이런식으로 CSV로 작성하고
[System.Serializable]
public class DialogueData // 대화 데이터를 담는 그릇 역할
{
public string ID;
public string NpcName;
public string Condition;
public string Text;
}
using System.Collections.Generic;
using UnityEngine;
public class DialogueManager : MonoBehaviour
{
public static DialogueManager Instance;
public TextAsset csvFile; // 유니티 인스펙터에서 CSV 파일을 연결할 변수
// NPC 이름, 상태, 대화 ID를 키로 사용하는 딕셔너리
private Dictionary<string, List<DialogueData>> dialogueDatabase;
public List<DialogueData> allDialogues;
private void Awake()
{
if (Instance == null)
{
Instance = this;
LoadDialogueData();
DontDestroyOnLoad(gameObject);
}
else
{
Destroy(gameObject);
}
}
// 파싱작업
private void LoadDialogueData()
{
dialogueDatabase = new Dictionary<string, List<DialogueData>>();
string[] lines = csvFile.text.Split('\n'); // 데이터를 한 줄씩 나눔
for (int i = 1; i < lines.Length; i++)
{
string line = lines[i];
if (string.IsNullOrEmpty(line)) continue;
string[] values = line.Split(","); // 한 줄의 콤마로 열을 나눔
string replaceText = values[3].Replace("`", ","); // 대사에 콤마대신 썼던 `를 다시 콤마로 변환
if (values.Length < 4) continue;
// CSV 파일에서 읽어온 데이터를 기반으로 DialogueData라는 새로운 객체를 생성
DialogueData data = new DialogueData
{
ID = values[0],
NpcName = values[1],
Condition = values[2],
Text = replaceText,
};
// 딕셔너리에 대화 데이터 저장
string key = $"{data.NpcName}_{data.Condition}";
if (!dialogueDatabase.ContainsKey(key))
{
dialogueDatabase[key] = new List<DialogueData>();
}
dialogueDatabase[key].Add(data);
allDialogues.Add(data);
}
}
// 해당 매개변수의 조건에 충족하는 대화를 가져옴
public List<DialogueData> GetDialogues(string npcName, string condition)
{
string key = $"{npcName}_{condition}";
if (dialogueDatabase.ContainsKey(key))
{
return dialogueDatabase[key];
}
return new List<DialogueData>();
}
}
private IEnumerator HandleDialogueFlow() // 상황에 맞는 대사 출력
{
List<DialogueData> dialogue;
// 첫 상호작용 대화일 경우(currentDialogueFlag가 0001이 아닌 경우)
if (!HasDialogueFlag(DialogueFlags.HasSpokenFirstDialogue))
{
dialogue = DialogueManager.Instance.GetDialogues("UpgradeNpc", "First_Meet");
yield return StartCoroutine(Dialogue(dialogue));
// 현재 대화 상태를 첫 상호작용 한 걸로 표시 (0000 -> 0001로 변경)
SetDialogueFlag(DialogueFlags.HasSpokenFirstDialogue);
}
else
{
dialogue = DialogueManager.Instance.GetDialogues("UpgradeNpc", "Default");
yield return StartCoroutine(Dialogue(dialogue));
}
dialogueCoroutine = null;
}
private IEnumerator Dialogue(List<DialogueData> dialogues) // 대화 코루틴
{
SubtitleUI sUI = UIManager.Instance.GetUI<SubtitleUI>();
sUI.isDialogue = true;
foreach (DialogueData data in dialogues)
{
isEndDialogue = false;
sUI.CallSubtitle(data.Text, true); // 대사 출력
// isEndDialogue가 true가 될 때까지 현재 코루틴을 일시 중지 시킴
yield return new WaitUntil(IsEndDialogue);
}
UIManager.Instance.Close<SubtitleUI>();
UIManager.Instance.Open<TacticalCoreUI>(); // 전술 코어 UI 활성화
sUI.isDialogue = false;
}
HandleDialogueFlow()에서 조건에 맞는 대화를 가져오고
Dialogue()에서 해당 조건의 맞는 대사를 data.Text로 출력한다.