Notice
Recent Posts
Recent Comments
Link
«   2025/01   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
Tags
more
Archives
Today
Total
관리 메뉴

zyeon's 작심삼일 코딩 공부

대화·퀘스트 시스템 - (4) 퀘스트 본문

unity

대화·퀘스트 시스템 - (4) 퀘스트

젼뀨 2024. 9. 12. 22:20

퀘스트의 이름과 그 퀘스트에 관련된 NPC ID 배열을 저장하는

퀘스트 데이터 클래스를 작성한다.

public class QuestData
{
    public string questName = "";
    public int[] npcId = { };

    public QuestData(string name, int[] id)
    {
        this.questName = name;
        this.npcId = id;
    }
}

블로그에서는 글이 너무 길어져 생략하지만

퀘스트 매니저도 호출하기 쉽게 싱글톤으로 작성해주었다. 

public class QuestManager : MonoBehaviour
{
    public int questId;
    public int questActionIndex;
    [SerializeField] GameObject[] m_questObject;
    Dictionary<int, QuestData> m_questList;
    
    /* 싱글톤 코드 생략... */
    
    private void Awake()
    {
        /* 싱글톤 코드 생략... */
        GenerateQuest();
    }
    
    void GenerateQuest()
    {
        m_questList = new Dictionary<int, QuestData>();
    
        m_questList.Add(10, new QuestData("공주님의 부탁", new int[] { 1000, 1000 }));
        m_questList.Add(20, new QuestData("린다에게 조언 듣기", new int[] { 3000, 2000, 1000 }));
        m_questList.Add(30, new QuestData("공주님에게 별 갖다주기", new int[] { 1000 }));
        m_questList.Add(40, new QuestData("첫번 째 퀘스트 끝", new int[] { 0 }));
    
        if (!PlayerPrefs.HasKey("QuestID"))
            PlayerPrefs.SetInt("QuestID", questId);
        else
            questId = PlayerPrefs.GetInt("QuestID");
    
    }

Awake()에 퀘스트 생성 함수를 호출하여, 씬이 로드될 때 퀘스트가 생성된다.

퀘스트 리스트는 Quest ID 와 QuestData 객체를 매핑하는 역할을 해준다.

 

예를 들어 m_questList.Add(10, new QuestData("공주님의 부탁", new int[] { 1000, 1000 })); 와 같은 퀘스트는 

  • 퀘스트 ID : 10
  • 퀘스트 이름: 공주님의 부탁
  • NPC ID가 1000인 NPC와 두 번 상호 작용한다.

이와 같은 내용의 퀘스트이다.

 

퀘스트는 10 →20 →30 →40과 같이 퀘스트 id에 따라 진행시킬 것 이기 때문에

퀘스트 진행 상황을 PlayerPrefs에 저장해 주었다.

public void CheckQuest(int id)
{
    questId = PlayerPrefs.GetInt("QuestID");

    //다음 대화로
    if (id == m_questList[questId].npcId[questActionIndex] && QuestCondition())
    {
        questActionIndex++;
    }
    ControlObject();

    //퀘스트 마지막 대화 후 다음 퀘스트로
    if (questActionIndex == m_questList[questId].npcId.Length && QuestCondition())
        NextQuest();
}

CheckQuest()는 특정 NPC와 상호작용할 때 퀘스트의 진행 상황을 확인하고, 퀘스트 완료 시

NextQuest()를 이용해 다음 퀘스트로 넘겨준다.

더보기

▼NextQuest()

void NextQuest()
{
    questId += 10;
    PlayerPrefs.SetInt("QuestID", questId);
    questActionIndex = 0;
}

 

퀘스트 ID가 10 단위로 구분되어 있기 때문에

퀘스트 ID를 10 더해주어 다음 퀘스트로 넘겨준다.

 

퀘스트 진행상황을 유지할 수 있게 PlayerPrefs에 저장해준다.

 

퀘스트 진행 단계를 다시 0으로 초기화 해주어 다음 퀘스트를 처음부터 시작할 수 있게 해준다.

 

현재 상호작용한 NPC와 현재 퀘스트 단계의 NPC가 일치하고,

QuestCondition()로 다른 퀘스트 시작 조건이 충족되는지 확인 되면 

퀘스트의 다음 단계로 넘어간다.

더보기

▼ QuestCondition()

//퀘스트 시작 조건
bool QuestCondition()
{
    bool result = true;

    switch (questId) //퀘스트 성공 조건이 있는 부분 작성
    {
        case 10:
            break;

        case 20:
            if (questActionIndex == 3 && PlayerPrefs.GetInt("Star") < 5)
                result = false;
            break;

        case 30:
            break;
    }
    if (result == false) questActionIndex--;
    return result;
}

 

만약 퀘스트 시작 조건에 충족하지 못한다면

퀘스트 진행 상황을 원래대로 되돌린다.

ControlObject()로 퀘스트와 관련된 오브젝트를 제어한다.

더보기

▼ ControlObject()

void ControlObject()
{
    switch (questId)
    {
        case 10:
            break;

        case 20:
            if (questActionIndex == 2) //린다랑 대화 끝났을 때 숲으로 가는 길을 열어준다.
            {
                m_questObject[0].SetActive(false); //0: roadblock
                PlayerPrefs.SetInt("RoadBlock", 1);
            }
            break;

        case 30:
            if (questActionIndex == 1) //공주랑 대화가 끝나면 
            {
                int star = PlayerPrefs.GetInt("Star") - 5;
                PlayerPrefs.SetInt("Star", star);
                int hp = PlayerPrefs.GetInt("FullHP") + 1;
                PlayerPrefs.SetInt("FullHP", hp);

                GameObject.Find("Canvas").GetComponent<StarTextMain>().SetStar();
            }
            break;
        case 40:
            break;
    }
}

 

퀘스트를 무사히 완료할 시 일어나는 변화들을 관리한다.

public int GetQuestDialogIndex(int id)
{
    return questId + questActionIndex;
}

대사 출력 시 필요한 퀘스트 ID를 받아오기 위한 함수도 작성해주면 퀘스트 끝.