[TIL] 19일 차 - Unity에서 대화창 구현하기

ChangBeom·2025년 2월 20일

TIL

목록 보기
20/53
post-thumbnail

오늘은 개인 프로젝트를 제출하고 구현이 아쉬웠던 부분을 찾던 도중 대화창을 조금 더 발전 시킬 수 있을 것 같아서 조금 더 디벨롭 해볼 예정이다.

[1. 내가 구현한 대화창]

일단 내가 생각하고 구현한 로직은 다음과 같다.

  1. 상호작용 가능한 오브젝트가 대화 내용을 들고 있음
  2. 그 오브젝트와 상호작용하게 되면 오브젝트가 대화 내용을 대화창 UI에 보내줌
  3. 대화창 UI가 열리고 넘겨 받을 대화 내용을 출력함

이 생각을 토대로 아래와 같이 코드를 짰다.

1. BugNPC라는 클래스에서 talkData를 가지고 있고, Interactive()를 호출하면 chatUI의 GetData를 통해 대화 내용을 넘겨준다.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class BugNPC : BaseInteractiveObjects
{
    UIManager uiManager;
    ChatUI chatUI;

    string[] talkData;
    SpriteRenderer portrait;

    private void Start()
    {
        GameObject canvas = GameObject.Find("Canvas");

        if (canvas != null)
        {
            uiManager = canvas.GetComponent<UIManager>();
            chatUI = uiManager.GetComponentInChildren<ChatUI>(true);
        }
        else
        {
            Debug.LogError("Canvas가 없습니다.");
        }

        talkData = new string[]
        {
            "사사사사삭.....",
            "사사삭.....사사삭....사사사사삭.....",
            "(평범한 벌레인 것 같다.)"
        };

        portrait = GetComponent<SpriteRenderer>();
    }


    public override void Interactive()
    {
        base.Interactive();
        chatUI.GetData(talkData, portrait.sprite);
        uiManager.ChangeState(UIState.Chat);
    }

    public override void OffKey()
    {
        base.OffKey();
        uiManager.ChangeState(UIState.Game);
    }
}

2. ChatUI 클래스에서 넘겨 받은 대화 내용을 스페이스바를 누를 때마다 하나 씩 UI에 출력해준다.

using System.Collections;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
using UnityEngine.UI;

public class ChatUI : BaseUI
{
    [SerializeField] private TextMeshProUGUI chatText;
    [SerializeField] private Image portrait;
    private string[] talkData;
    private int currentIndex;

    private void OnEnable()
    {
        currentIndex = 0;
        UpdateDialogue();
    }

    private void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space))
        {
            NextTalk();
        }
    }

    public void NextTalk()
    {
        currentIndex++;
        if (currentIndex < talkData.Length)
        {
            UpdateDialogue();
        }
        else
        {
            uiManager.ChangeState(UIState.Game);
        }
    }
    public void GetData(string[] arr, Sprite sp)
    {
        talkData = arr;
        portrait.sprite = sp;
    }

    void UpdateDialogue()
    {
        chatText.text = talkData[currentIndex];
    }

    protected override UIState GetUIState()
    {
        return UIState.Chat;
    }
}

정리하면 아래와 같은 순서대로 진행된다.

플레이어가 BugNPC와 상호작용을 진행 -> BugNPC가 ChatUI에 데이터를 넘겨줌 -> ChatUI는 넘겨 받은 데이터를 대화형식으로 출력해줌


그런데 이 코드는 큰 오류가 하나 존재한다.

바로 양방향 대화 구조가 아닌 오브젝트가 단방향으로 말을 하는 구조인 것이다.

그래서 나는 조금 더 공부해서 플레이어와 오브젝트가 양방향으로 대화하는 구조를 만들 것이다.


[2. 양방향 대화창 구현]

양방향 대화창을 구현하기 위해 구글링을 하던 도중 내가 만든 로직을 그대로 사용하면서 양방향 대화창을 구현할 수 있는 아이디어를 알아냈다.

그것은 문자열 Split을 사용하는 것이다.

NPC가 들고 있는 대화 문자열에 누가 말하는 것인지 구분자 ":" 를 활용해서 표시해준다.

여기서 ":0"이 붙은 문자열은 NPC의 대사이고, ":1"이 붙은 문자열은 플레이어의 대사이다.

이를 활용하여 ChatUI의 UpdateTalk(수정 전에는 UpdateDialogue 라는 이름이다.)를 아래와 같이 수정하면 된다.

위 코드를 간단하게 설명하자면, 문자열을 구분자 ":"를 기준으로 Split 했을 때 숫자가 0이면 NPC의 초상화를 띄우고, 숫자가 1이면 플레이어의 초상화를 띄운다. 이후 대사를 출력하는 로직이다.

이런식으로 문자열을 Split해서 얻은 값을 활용해서 NPC와 플레이어의 초상화를 출력해주면 자연스럽게 양방향 대화가 이루어진다.

0개의 댓글