본문 바로가기
카테고리 없음

유니티3D - NPC와 대화창 (설명편)

이번 게시글에서는 지난번에 작동해보았던 NPC와 대화창 스크립트에 대한 설명을 드리도록 하겠습니다.

https://itadventure.tistory.com/425

 

유니티3D - NPC와 대화창

지난 게시글에서는 군중 NPC들을 띄우는 부분과 그 중에서 하나의 NPC를 프리팹으로 구워서 사용하는 방법을 알아보았습니다. https://itadventure.tistory.com/424 유니티3D - NPC 랜덤 메이커 UMA! ( 유니티

itadventure.tistory.com

지난번에 입력한 스크립트는 다음 4가지 종류의 오브젝트가 통신하는 구조로 되어 있는데요.

동작방식을 함축하면 아래와 같습니다.

- 2)메인스크립트는 플레이를 시작하자마다 대화창을 감춥니다.
  대사란은 대화창에 소속되어 있기 때문에 함께 감춰집니다.
  이 때 잽싸게 대화창과 대사를 제어할 수 있도록 내부 프로퍼티에 컴포넌트 참조로 넣어 버립니다.

- 1)트리거에 플레이어가 진입하면 2)메인스크립트에 '입장신호'를 알립니다.
  이 때 대화창에 표시할 대사도 함께 넘겨줍니다
 
- 2)메인스크립트는 '입장신호'가 들어오면 3)다이얼로그창을 보이도록 합니다.
  그리고 4)대사란에 넘겨받은 대사를 표시합니다.
  
- 1)트리거에서 플레이어가 탈출하면 2)메인스크립트에 '퇴장신호'를 알립니다.

- 2)메인스크립트는 '퇴장신호'가 들어오면 3)다이얼로그창을 감춥니다.

우선 Main 이라는 오브젝트는 비록 보이지 않지만 Scene 내부에 존재하기 때문에
시작하자마자 스크립트가 작동합니다.

Main 오브젝트에는 MainScript 라는 스크립트가 들어 있는데요.
스크립트 내용은 아래와 같습니다.

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

public class MainScript : MonoBehaviour
{
    private GameObject NPCDialog;
    private Text NPCText;

    void Start()
    {
        NPCDialog = GameObject.Find("NPCDialog");
        NPCText = GameObject.Find("NPCText").GetComponent<Text>();
        NPCDialog.SetActive(false);
    }

    public void NPCChatEnter(string text)
    {
        NPCText.text = text;
        NPCDialog.SetActive(true);
    }

    public void NPCChatExit()
    {
        NPCText.text = "";
        NPCDialog.SetActive(false);
    }    
}

플레이를 시작하면 제일 먼저 Start() 메소드가 실행이 되는데요.
아래 3줄이 먼저 실행이 됩니다.

NPCDialog = GameObject.Find("NPCDialog");
NPCText = GameObject.Find("NPCText").GetComponent<Text>();
NPCDialog.SetActive(false);

이 중에서 아래 명령은,

NPCDialog = GameObject.Find("NPCDialog");

NPCDialog 라고 이름을 지어준 다이얼로그 창을 찾아서 MainScript 컴포넌트의 NPCDialog 에 넣어줍니다.
NPCDIalog 프로퍼티는 소스 위쪽에 이렇게 선언되어 있습니다.

private GameObject NPCDialog;

아울러 아래 명령도 역시 대사컴포넌트를 찾아주는데요,

NPCText = GameObject.Find("NPCText").GetComponent<Text>();

위와는 약간 다릅니다. 이 경우 대사창 오브젝트 자체가 아니라,
대사창 오브젝트의 Text 라는 컴포넌트를 찾아 NPCText에 넣어줍니다.

대사만 제어한다고 볼 때 이렇게 찾아놓는 편이 나중에 제어하기가 더 쉽습니다.

단 이 경우 저장하는 프로퍼티 또한 GameObject 가 아닌 Text 로 선언해주어야 합니다.
아래처럼요.

private Text NPCText;

그리고 이어서 대화창 다이얼로그를 감춥니다. 아래 스크립트가 실행되면서 대화상자가 플레이 화면에서 사라지게 되는데요.

NPCDialog.SetActive(false);

이 동작은 다이얼로그 오브젝트의 체크상자를 해제하는 것과 동일합니다.
플레이 도중 직접 마우스로 이 체크상자를 클릭하는 것을 스크립트가 대신 수행해주는 것이지요.

이제 시작하자마다 대화창과 대사란을 참조로 받아놯기 때문에 더 이상 못찾을 염려는 없게 되었습니다.
나머지 스크립트 내용은 트리거에 의해 반응형으로 작동하기 때문에 트리거를 먼저 살펴보겠습니다.

트리거에는 아래와 같은 스크립트가 들어 있는데요.

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

public class NPC_Trigger : MonoBehaviour
{
    public string ChatText = "";
    private GameObject Main;

    void Start()
    {
        Main = GameObject.Find("Main");
    }

    private void OnTriggerEnter(Collider other)
    {
        if (other.tag == "myplayer")
        {
            Main.GetComponent<MainScript>().NPCChatEnter(ChatText);
        }
    }

    private void OnTriggerExit(Collider other)
    {
        if (other.tag == "myplayer")
        {
            Main.GetComponent<MainScript>().NPCChatExit();
        }
    }
}

트리거 또한 플레이를 시작하자마다 하는 일이 있습니다.
바로 Main 이라는 이름을 갖는 오브젝트를 찾아 놓는 것입니다.
좀 더 빠른 처리를 위해 미리 찾아다 저장해 놓는 것이지요.

Main = GameObject.Find("Main");

그리고 트리거에 무언가의 물체가 충돌이 감지되면 충돌이벤트가 발생하는데요.

트리거의 경우 충돌이벤트가 발생할 때 OnTriggerEnter() 라는 메소드가 자동 실행됩니다.

메소드 내용은 아래와 같이 되어 있는데요.

private void OnTriggerEnter(Collider other)
{
     :
}

괄호 안의 Collider other 라는 부분은 충돌한 대상 물체를 의미합니다.
이를 파라미터라고 하는데요. Collider 는 넘겨받은 파라미터가 충돌체 형태의 컴포넌트라는 뜻입니다.
그리고 other 는 실제로 제어할 변수인데 꼭 other 일 필요는 없이 의미상의 이름을 주어도 됩니다.

이제 충돌한 물체가 플레이어인지를 검사합니다.
우리는 플레이어에게 'myplayer'라는 태그속성을 주었기 떄문에 아래 조건이 맞으면 중괄호 안쪽 영역이 실행됩니다.

if (other.tag == "myplayer")
{
     :
}

조건이 맞으면 아래 스크립트를 실행합니다.

Main.GetComponent<MainScript>().NPCChatEnter(ChatText);

여기서 이 부분은

Main.GetComponent<MainScript>()

Main 오브젝트에 소속된 MainScript 라는 컴포넌트를 찾는 부분입니다.
금방 전까지 살펴보았던 스크립트이지요

그리고 이 MainScript 컴포넌트의 NPCChatEnter(); 를 실행합니다.

NPCChatEnter(ChatText);

참고로 ChatText 는 트리거 오브젝트에 미리 입력해놓은 채팅 텍스트를 의미합니다.

아래와 같은 내용을 입력해 놓았었지요. 이 내용을 그대로 넘겨주는 것입니다.

<color=#ff7777>[NPC]</color>자모 월드에는 <size=20><color=#ffff33>즐거움</color></size> 이 있어요!

MainScript 에는 실제로 NPCChatEnter() 라는 메소드가 정의되어 있습니다.

public void NPCChatEnter(string text)
{
    NPCText.text = text;
    NPCDialog.SetActive(true);
}

내용은 별거 없습니다.
넘겨받은 ChatText 내용을 아까전에 찾아놓은 대사창의 Text 컴포넌트에 대사로 넣어 버립니다.

NPCText.text = text;

이 때 트리거에서는 ChatText 라는 이름으로 넘겨주었지만 여기서는 text 라는 이름으로 받아서 사용하는데요.
넘겨받는 쪽에서는 이름을 새로 정할수 있으므로 큰 상관은 없습니다.

public void NPCChatEnter(string text)
{
    :
}

그리고 이어서 대화창 다이얼로그 창이 보이도록 활성화합니다.

NPCDialog.SetActive(true);

그 반대로 자모 로봇이 트리거 영역에서 탈출하는 순간에도 이벤트가 발생합니다.
트리가 탈출 이벤트라고 해서, 아래 메소드가 자동 실행되는데요.

private void OnTriggerExit(Collider other)
{
    :
}

이 때도 역시 내 플레이어 캐릭터가 탈출한 것인지를 따져봅니다.

if (other.tag == "myplayer")
{
    :
}

맞다면 Main 오브젝트에 있는 MainScript 를 찾아 NPCChatExit() 라는 메소드를 실행합니다.

Main.GetComponent<MainScript>().NPCChatExit();

MainScript 에서 이 메소드 역시 아주 간결합니다.

public void NPCChatExit()
{
    NPCText.text = "";
    NPCDialog.SetActive(false);
}

대사란의 내용을 비워주고

NPCText.text = "";

대화창을 감춥니다.

NPCDialog.SetActive(false);

그래서 이와 같이 플레이어가 NPC 주위를 떠날 때,
대화창이 '뿅'하니 사라지는 것이지요.


이상으로 NPC와 대화창의 스크립트에 대한 설명이었습니다.
이해가 좀 수월하시려나 모르겠군요 :)

부디 필요하신 분에게 도움이 되셨기를 소망합니다.
오늘도 여기까지 읽어주셔서 감사합니다 :)


다음게시글 : 대화창에서 NPC를 바라보는 카메라 #1

https://itadventure.tistory.com/427

 

유니티3D - 대화창에서 NPC 를 바라보는 카메라 #1

지난 게시글에서는 NPC곁에 다가가면 대화창이 나오는 부분을 살펴보았었지요. https://itadventure.tistory.com/426 유니티3D - NPC와 대화창 (설명편) 이번 게시글에서는 지난번에 작동해보았던 NPC와 대화

itadventure.tistory.com