유니티 퀘스트 시스템 구현

박지예·2021년 9월 7일
1

공부

목록 보기
4/42

본 글은 이전 글과 이어집니다
전 글

퀘스트 시스템을 구현하고 있다...

골드메탈 유니티 링크

정말 너무너무 어려워서 머리가 깨질껏 같다

하나씩 하나씩 짚어보자

(앞으로 나올 설명은 유튜브 강의를 전부 따라하고 나서 쓴 글이라 중간 과정이 생략 되어 있을 수 있다.)

전 글에서도 다뤘듯이 플레이어가 오브젝트를 스캔한다.

//Scan Object
        if (Input.GetButtonDown("Jump") && scanObject != null)
            gameManager.Action(scanObject);

그 뒤 Action 함수

    public void Action(GameObject scanObj)
    {
        //Get Current Data
        scanObject = scanObj;
        ObjData objdata = scanObject.GetComponent<ObjData>();
        Talk(objdata.id, objdata.isNPC);
        //Visible Talk for Action
        talkPanel.SetActive(isAction);
    }

이곳에서 각 오브젝트의 아이디와 NPC여부를 Talk함수에 넣어준다.

(오브젝트의 아이디와 NPC여부는 `Obj Data'에서 관리)


이제 시작이다...

void Talk(int id, bool isNPC)
    {
        //Set Talk Data
        int questTalkIndex = questManager.GetQuestTalkIndex(id);
        string talkData =  talkManager.GetTalk(id + questTalkIndex, talkindex);
        //EndTalk
        if (talkData == null)
        {
            isAction = false;
            talkindex = 0;
            Debug.Log(questManager.CheckQuest(id));
            return;
        }
        //Continue Talk
        if (isNPC)
        {
            TalkText.text = talkData.Split(':')[0];
            portraitImg.sprite = talkManager.GetPortrait(id, int.Parse(talkData.Split(':')[1]));
            portraitImg.color = new Color(1, 1, 1, 1);
        }
        else
        {
            TalkText.text = talkData;
            portraitImg.color = new Color(1, 1, 1, 0);
        }
        isAction = true;
        talkindex++;
    }

단순하게, 위에서 받은 오브젝트 아이디로 이러쿵 저러쿵 하고 있는 함수다. 이 글에서는 퀘스트 부분만 설명하겠다.
사실 나도 아직 이해 다 못했다


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

이 함수에서 퀘스트 아이디와 퀘스트 인덱스를 더한 값을 반환한다.

⬆초기값


 //Set Talk Data
        int questTalkIndex = questManager.GetQuestTalkIndex(id);
        string talkData =  talkManager.GetTalk(id + questTalkIndex, talkindex);

값을 받은 questTalkIndex 값을 talkData에 id와 더해서 넣어준다.


TalkManager의 함수 GetTalk

public string GetTalk(int id, int talkindex)
    {
        if (!talkData.ContainsKey(id))
        {
            if (!talkData.ContainsKey(id - id % 10))
                return GetTalk(id - id % 100, talkindex); //Get first Talk
            else
                return GetTalk(id - id % 10, talkindex); //Get First Quest Talk
        }
        if (talkindex == talkData[id].Length)
            return null;
        else 
            return talkData[id][talkindex];
    }

talkData의 키 값이 아까 위에서 더한 값에 없으면, if문 안으로 들어가서 다시 다른값을 찾아주어야 한다.

여기서 잠깐!
talkData

//TalkData
        //NPC1:1000, NPC2:2000
        ////Box:100 , Dexk:200
        talkData.Add(1000, new string[] { "안녕?:0", 
                                          "이곳에 처음 왔구나?:1",
                                          "한 번 둘러 보도록 해:0"});
        talkData.Add(2000, new string[] { "이봐.:1", 
                                          "이 호수는 정말 아름답지?:0", 
                                          "호수 밑 바닥에 무언가가 숨겨져 있을 지도 몰라.:1" });
        talkData.Add(3000, new string[] { "평범한 나무 상자다." });
        talkData.Add(4000, new string[] { "누군가 사용한적 있는 책상이다." });
        //Quest Talk
        talkData.Add(10 + 1000, new string[] { "어서 와:0",
                                          "이 마을에 놀라운 전설이 있다는데:1",
                                          "오른쪽 호수에 가면 루도가 알려줄꺼야:0"});
        talkData.Add(11 + 1000, new string[] { "아직 못 찾았어?:0" });
        talkData.Add(11 + 2000, new string[] { "이봐.:1",
                                          "이 호수의 전설을 들으러 온거야?:0",
                                          "그럼 일 좀 하나 해주면 좋을텐데...:1",
                                           "내 집 앞에 떨어진 동전을 좀 주워줘:0"});
        talkData.Add(20 + 1000, new string[] { "루도의 동전?:1",
                                               "돈을 흘리고 다니면 어쩐담!:3",
                                               "나중에 루도에게 한마디 해줘야겠어!:3"});
        talkData.Add(20 + 2000, new string[] { "찾으면 꼭 가져다줘:1"});
        talkData.Add(20 + 5000, new string[] { "근처에서 동전을 찾았다." });
        talkData.Add(21 + 2000, new string[] { "엇, 찾아줘서 고마워.:2" });

다시 돌아와서 스캔한 오브젝트의 아이디와 현제 진행중인 퀘스트의 번호를 더한 값이 데이터에 없을때,
본인에다 본인을 10으로 나눈 나머지를 뺀다 = 일의 자리 수를 뺀다
그래도 없으면,
본인에다 본인을 100으로 나눈 나머지를 뺀다 = 십의 자리 수까지를 뺀다
그렇게 해서 개발자가 원하는 퀘스트 진행 방향이 아닐때도 키값을 바꿔 return해주면 된다..!

재귀함수를 써서 값이 나올때 까지 계속 호출!!


그렇게 한 대화를 다 끝내고 다음으로 넘어갈땐

talkindex++;

해준다. 그렇게 한 퀘스트가 끝나게 되면(같은 퀘스트 번호에서 마지막 대사까지 출력되면

if (talkindex == talkData[id].Length)
            return null;
        else 
            return talkData[id][talkindex];

null 을 반환해준다.


여기서 현제 어떤 퀘스트가 진행되고 있는지 콘솔창에 띄워줄꺼다

요로케

if (talkData == null)
       {
           isAction = false;
           talkindex = 0;
           Debug.Log(questManager.CheckQuest(id));
           return;
       }

CheakQuest

 public string CheckQuest(int id)
    {
        //Next Talk Target
        if(id == questList[questId].npcId[questActionIndex])
            questActionIndex++;
        //Control Quest Object
        ControllObject();
        //Talk Complete & Next Quest
        if (questActionIndex == questList[questId].npcId.Length)
            NextQuest();
        //Quest Name
        return questList[questId].questName;
    }

여기서 잠깐!!(퀘스트 리스트)

 void GenerateData()
    {
        questList.Add(10, new QuestData("마을 사람들과 대화하기",
                                        new int[] { 1000, 2000 }));
         questList.Add(20, new QuestData("루도의 동전 찾아주기",
                                        new int[] { 5000, 2000 }));                             
         questList.Add(30, new QuestData("퀘스트 올 클리어!",
                                        new int[] {0}));
    }

퀘스트 리스트에 저장되어 있는 퀘스트를 진행하는데 받아와야하는 오브젝트의 아이디를 모두 받아왔다면 questActionIndex를 증가하여

 talkData.Add(11 + 1000, new string[] { "아직 못 찾았어?:0" });

요롷게 퀘스트를 진행 할때의 대화를 관리 할 수 있다.
questActionIndex가 끝이라면 다음 퀘스트로 넘어간다.

void NextQuest()
   {
       questId += 10;
       questActionIndex = 0;
   }
profile
언젠간 바다로 갈거야!🐋

0개의 댓글