NPCdata.cs
using UnityEngine;

[CreateAssetMenu(fileName = "NewNPCData", menuName = "Dialogue/NPC Data")]
public class NPCData : ScriptableObject
{
    public string npcName;
    public string[] dialogueLines;
}

 

NPC 대화정보를 스크립터블 오브젝트로 관리하고 DialogueManager.cs, NPC.cs에 참조한뒤

 

매니저를 통해 npc에 데이터를 전달한다.

더보기
using UnityEngine;
using TMPro;

public class DialogueManager : MonoBehaviour
{
    public static DialogueManager Instance;

    [SerializeField] private TextMeshProUGUI dialogueText;
    [SerializeField] private TextMeshProUGUI npcNameText;
    [SerializeField] private GameObject dialoguePanel;

    private NPCData currentNPCData;    
    private int dialogueIndex;

    private void Awake()
    {
        if (Instance == null)
            Instance = this;
        else
            Destroy(gameObject);

        dialoguePanel.SetActive(false);
    }

    
    public void StartDialogue(NPCData npcData)
    {
        currentNPCData = npcData;
        dialogueIndex = 0;
        
        dialoguePanel.SetActive(true);

        // NPC 이름 표시
        npcNameText.text = currentNPCData.npcName;

        // 첫 대화 출력
        NextDialogue();
    }

    public void NextDialogue()
    {
        // 대화 종료
        if (dialogueIndex >= currentNPCData.dialogueLines.Length)
        {
            EndDialogue();
            return;
        }

        // 대화 출력
        dialogueText.text = currentNPCData.dialogueLines[dialogueIndex];
        dialogueText.gameObject.SetActive(true);

        dialogueIndex++;
    }
    
    public void EndDialogue()
    {
        dialoguePanel.gameObject.SetActive(false);
        dialogueText.text = string.Empty;
        npcNameText.text = string.Empty;
    }
    
    public bool DialogueActive()
    {
        return dialoguePanel.activeSelf;
    }

대화 text, npc 이름, panel을 변수로 선언하고

 

npc 데이터를 매개변수로 전달해준다.

 

dialouge 인덱스 번호에 따라 대화를 다르게 출력한다.

 

DialougeActive 함수를 통해 패널 활성화 여부를 판단하여 켜고 끄고를 반복해준다.

더보기
NPC.cs
using UnityEngine;

public class NPC : MonoBehaviour
{
    public NPCData npcData; 
    private bool isPlayerNearby;

    private void Update()
    {
        if (isPlayerNearby && Input.GetKeyDown(KeyCode.E))
        {
            if(DialogueManager.Instance.DialogueActive())
            {
                DialogueManager.Instance.NextDialogue();
            }
            else
            {
                DialogueManager.Instance.StartDialogue(npcData);
            }
        }
    }

    private void OnTriggerEnter2D(Collider2D other)
    {
        Player player = other.GetComponent<Player>();
        if (player) 
        {
            isPlayerNearby = true;
        }
    }
    

    private void OnTriggerExit2D(Collider2D other)
    {
        Player player = other.GetComponent<Player>();
        if (player)
        {
            isPlayerNearby = false;
            DialogueManager.Instance.EndDialogue();
        }
    }

 

플레이어가 조건(근접(TriggerEnter)또는 벗어날때(TriggerExit))에 따라 

매니저를 통해 전달받은 StartDialouge, EndDialouge 함수를 호출해준다.

 

일단 E키 상호작용 getkeydown으로 했는데 인풋시스템으로 리펙토링 하면 좋을 것 같다. 

 

 

콜라이더 범위를 설정하여 다가가면 상호작용 할 수 있도록 설정

+ Recent posts