Unity C# 대화 선택지 로직 구현

이시율·2025년 5월 1일

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에 따라 소스 내용 변화도 체크해야할 것 같다.

0개의 댓글