오늘은 개인 프로젝트를 제출하고 구현이 아쉬웠던 부분을 찾던 도중 대화창을 조금 더 발전 시킬 수 있을 것 같아서 조금 더 디벨롭 해볼 예정이다.
일단 내가 생각하고 구현한 로직은 다음과 같다.
- 상호작용 가능한 오브젝트가 대화 내용을 들고 있음
- 그 오브젝트와 상호작용하게 되면 오브젝트가 대화 내용을 대화창 UI에 보내줌
- 대화창 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는 넘겨 받은 데이터를 대화형식으로 출력해줌
그런데 이 코드는 큰 오류가 하나 존재한다.
바로 양방향 대화 구조가 아닌 오브젝트가 단방향으로 말을 하는 구조인 것이다.
그래서 나는 조금 더 공부해서 플레이어와 오브젝트가 양방향으로 대화하는 구조를 만들 것이다.
양방향 대화창을 구현하기 위해 구글링을 하던 도중 내가 만든 로직을 그대로 사용하면서 양방향 대화창을 구현할 수 있는 아이디어를 알아냈다.
그것은 문자열 Split을 사용하는 것이다.
NPC가 들고 있는 대화 문자열에 누가 말하는 것인지 구분자 ":" 를 활용해서 표시해준다.

여기서 ":0"이 붙은 문자열은 NPC의 대사이고, ":1"이 붙은 문자열은 플레이어의 대사이다.
이를 활용하여 ChatUI의 UpdateTalk(수정 전에는 UpdateDialogue 라는 이름이다.)를 아래와 같이 수정하면 된다.

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





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