게임에서 퀘스트는 방향성을 제공해 주고 게임의 목적성과 재미를 높여주며, 진행 상황을 추적하고 보상을 제공하여 게임을 보다 흥미롭게 만들어줍니다. 퀘스트 시스템을 구현하고 정리하였습니다.

 

💬 서론

  • 본 글은 게임을 모두 만든 후에 작성한 글로 핵심 주제 외 클래스 및 다른 기능에 대한 함수가 포함될 수 있습니다.

 

📖 구현 내용

  • 적 처치, 아이템 습득에 대한 퀘스트를 구현합니다.
  • 플레이어는 퀘스트를 받고 퀘스트를 완료할 수 있습니다.
  • 퀘스트 상태를 확인하여 상태별로 이벤트를 처리할 수 있습니다.
  • 스크립터블 오브젝트로 퀘스트의 데이터를 관리합니다.
  • 스크립터블 오브젝트를 프로젝트 폴더 내에서 관리하고, 이 데이터를 자동으로 불러옵니다.
  • ID를 이용하여 고유한 퀘스트의 중복 여부를 검사할 수 있습니다.
  • 하나의 퀘스트에서 여러 개의 목표 중 하나만 수행해도 퀘스트를 완료하는지에 대한 여부를 설정할 수 있습니다.
  • 퀘스트 콘텐츠를 보여주고 현재 진행 시점, 완료한 퀘스트들의 정보를 볼 수 있습니다.

 

⚒️ 구현

  • 이번 글에서는 퀘스트 콘텐츠 매니저를 사용할 때 풀 사이즈 UI창을 구현하고 구성요소 중 하나인 QuestFullContent 프리팹에대해 다루겠습니다.

· FullContent

더보기
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using TMPro;
using UnityEngine.SceneManagement;

namespace Quest
{
    public class QuestFullContent : QuestCompactContent
    {
        [SerializeField] private Toggle? mCompactContentToggle;
        [SerializeField] private Button? mNaviButton;

        public override void UpdateCompactQuestContents(QuestContentData contentData)
        {
            base.UpdateCompactQuestContents(contentData);
        }

        public void CompleteQuest()
        {
            Destroy(mCompactContentToggle.gameObject);
            Destroy(mNaviButton.gameObject);

            NaviManager.Instance.TryStopNavi(mQuestData.name);
        }

        public void TOGGLE_CompactContent()
        {
            QuestContentManager.Instance.ToggleCompactQuestContent(mQuestData, mCompactContentToggle.isOn);
        }

        public void BTN_DisplayCurrentQuest()
        {
            QuestContentManager.Instance.ToggleFullQuestContent(mQuestData);
        }

        public void BTN_Navi()
        {
            Debug.Log(QuestManager.Instance.CheckQuestState(base.mQuestData.questId));

            if(SceneManager.GetActiveScene().name != base.mQuestData.questScene)
                return;

            if(mQuestData.name == NaviManager.Instance.NaviKeyName)
            {
                NaviManager.Instance.TryStopNavi(mQuestData.name);
                return;
            }

            switch(QuestManager.Instance.CheckQuestState(base.mQuestData.questId))
            {

                case QuestState.CLEAR:
                {
                    NaviManager.Instance.StartNavi(mQuestData.name, GameManager.Instance.Player.transform, base.mQuestData.sourcePos);
                    break;
                }
                case QuestState.ONGOING:
                {
                    NaviManager.Instance.StartNavi(mQuestData.name, GameManager.Instance.Player.transform, base.mQuestData.destinationPos);
                    break;
                }
            }
        }
    }
}

 

[SerializeField] private Toggle? mCompactContentToggle;
[SerializeField] private Button? mNaviButton;
  • 슬롯 프리팹 내부에 존재하는 토글과 버튼입니다.
  • 특정 함수에 의해 이 버튼들이 파괴될 수 있기에 nullable로 설정합니다.

 

public override void UpdateCompactQuestContents(QuestContentData contentData)
{
    base.UpdateCompactQuestContents(contentData);
}
  • 부모의 함수를 오버라이드하여 새롭게 정의합니다.
  • 풀사이즈UI는 내부에 특별히 업데이트를 할 콘텐츠가 없기에 컴팩트 UI에서 사용하는 텍스트를 사용하도록 요청합니다.

 

public void CompleteQuest()
{
    Destroy(mCompactContentToggle.gameObject);
    Destroy(mNaviButton.gameObject);

    NaviManager.Instance.TryStopNavi(mQuestData.name);
}
  • 퀘스트를 완료한경우 이 슬롯에도 함수가 호출되어 슬롯 내부의 컴팩트 UI표시 토글과 내비게이션 버튼을 파괴합니다.
  • 만약 이 퀘스트에 대한 내비게이션이 켜져있다면, 더 이상 필요하지 않으므로 내비게이션을 종료합니다.
  • 내비게이션에 대한 내용은 "[유니티] NavMesh를 응용하여 '내비게이션(경로 시각화)' 만들기"에서 확인할 수 있습니다.

 

public void TOGGLE_CompactContent()
{
    QuestContentManager.Instance.ToggleCompactQuestContent(mQuestData, mCompactContentToggle.isOn);
}

public void BTN_DisplayCurrentQuest()
{
    QuestContentManager.Instance.ToggleFullQuestContent(mQuestData);
}
  • UI에서 입력을 받아 호출되는 함수입니다.

 

public void BTN_Navi()
{
    Debug.Log(QuestManager.Instance.CheckQuestState(base.mQuestData.questId));

    if(SceneManager.GetActiveScene().name != base.mQuestData.questScene)
        return;

    if(mQuestData.name == NaviManager.Instance.NaviKeyName)
    {
        NaviManager.Instance.TryStopNavi(mQuestData.name);
        return;
    }

    switch(QuestManager.Instance.CheckQuestState(base.mQuestData.questId))
    {

        case QuestState.CLEAR:
        {
            NaviManager.Instance.StartNavi(mQuestData.name, GameManager.Instance.Player.transform, base.mQuestData.sourcePos);
            break;
        }
        case QuestState.ONGOING:
        {
            NaviManager.Instance.StartNavi(mQuestData.name, GameManager.Instance.Player.transform, base.mQuestData.destinationPos);
            break;
        }
    }
}
  • 내비게이션을 활성화합니다.
  • 이미 동일한 퀘스트에 대한 내비게이션이 활성화되어있다면, 내비게이션을 종료합니다.
  • 현재 퀘스트 상태를 고려하여 목적지로 향하는 내비게이션인지, 의뢰자 위치에 대한 내비게이션인지 판단하여 표시하도록 합니다.

 

· UI 설정 

  • 전체 구성은 다음과 같습니다.

 

✅ 사용

bonnate