Unity에서 대화 선택지에 따라 다르게 내용이 나오는 로직을 구현해봤다.
우선 Dialog 데이터 구조를 만든 다음
class Dialog
{
public string text;
public Dictionary<int, string> choice; // 선택지: 선택 번호와 내용
public string sceneToLoad;
}
NPC 이름에 따라 대화 내용이 다르도록 설정
public void DialogSetting()
{
dialogueArea.SetActive(true);
dialogStep = new Dictionary<int, Dialog>();
if (npcName == "Elf")
{
// 1단계: 질문 + 선택지
dialogStep.Add(1, new Dialog
{
text = "무슨 게임을 하고 싶어?",
choice = new Dictionary<int, string> {
{ 2, "Plane" },
{ 0, "아무것도 아니야" }
},
sceneToLoad = null
});
...
ShowDialog(1);
}
현재 단계의 Dialog를 가져와 대사를 UI에 출력하고, 선택지가 0일 때 기본적으로 대화가 종료되는 방향으로 만들었으며, sceneToLoad가 값이 들어가 있을 때 해당 값에 Scene를 불러오도록 구현 하였다.
public void ShowDialog(int step)
{
currentStep = step;
Dialog dialog = dialogStep[step];
dialogueText.text = dialog.text;
// 기존 선택지 버튼 삭제
foreach (Transform child in buttonParent.transform)
{
buttonParent.SetActive(false);
Destroy(child.gameObject);
}
// 선택지가 있다면 버튼 생성
if (dialog.choice != null)
{
buttonYPos = 0f;
foreach (var c in dialog.choice)
{
buttonParent.SetActive(true);
int nextStep = c.Key;
string choiceText = c.Value;
Button btnObj = Instantiate(choiceBtnPrefab, buttonParent.transform);
btnObj.transform.localPosition = new Vector3(0, buttonYPos -= buttonSpacing, 0);
btnObj.GetComponentInChildren<TMP_Text>().text = choiceText;
// 선택지에 따라 씬을 이동할 수도 있음
if (nextStep == 0) // 0번 선택지 선택 시 대화 종료
{
btnObj.onClick.AddListener(() => EndDialog()); // 대화 종료 처리
}
else
{
btnObj.onClick.AddListener(() => ShowDialog(nextStep)); // 대화 계속
}
}
}
if (!string.IsNullOrEmpty(dialog.sceneToLoad)) // 씬이 설정되어 있으면 씬 이동
{
ChangeScene(dialog.sceneToLoad);
}
}
}
대화 선택지 로직을 최대한 재사용이 가능하도록 하려다 보니 구현하다가 삭제한 소스들이 많고 시간도 많이 쓰게된 것 같다..
최대한 재사용이 가능하도록 만들었지만 특이한 NPC의 선택지 Case에 따라 소스 내용 변화도 체크해야할 것 같다.