728x90
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[System.Serializable] 
public class Quest
{
    public bool isSucess;//성공했는지확인여부
    public bool Progress;//진행중인지 확인여부
    public int questid;//퀘스트 id 
    
    public string goal;// 퀘스트 내용
    public string title;//퀘스트제목
    public string description;//퀘스트 설명 
    public List<Item> Rewarditems;//보상아이템
    public UnitCode UnitCode;//무슨 몬스터를 잡아야하는지 설정 
    public QuestGoal Questgoal;// 퀘스트타입 , 잡아야되는몬스터수 , 현재잡은몬스터수 , 클리어 npc id 
}

1. 영상처럼 quest 스크립트 생성후 위 코드 입력 

 

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

public class QuestGiver : MonoBehaviour
{
    public static QuestGiver instance;
    public List<Quest> quest;
    public CharacterManger character;
    public GameObject[] button;
    public GameObject questWindow;
    public Text titleText;
    public Text descriptionText;
    public GameObject[] rewardslot;
    public GameObject progerss;
    public GameObject sucess;

    private void Awake()
    {
        if (instance == null)
        {
            instance = this;

        }
    }
    public void OpenQuestWindow()//npc ㅌ
    {
        
            if(quest[CharacterManger.instance.questchapter].Progress==false&&quest[CharacterManger.instance.questchapter].isSucess==false)//quest[퀘스트진행도].progress,  issucees 가 false면 수락전 완료전 퀘스트 
            {
                questWindow.SetActive(true);//퀘스트 창 보이게 
            for(int i=0;i<button.Length;i++)//안보일 버튼들 추가해서 버튼들안보이게
            {
                button[i].SetActive(false);
            }
              
                titleText.text = quest[CharacterManger.instance.questchapter].title;//제목=quest[진행도].제목
                descriptionText.text = quest[CharacterManger.instance.questchapter].description;//설명=qeust[진행도].설명
                for (int j = 0; j < rewardslot.Length; j++)//보상아이템 이미지는 
                {
                    rewardslot[j].transform.GetChild(1).GetComponent<Image>().sprite = GameManger.instance.ItemSprite[GameManger.instance.Alltem.FindIndex
                        (x => x.Name == quest[CharacterManger.instance.questchapter].Rewarditems[j].Name)];//보상이템과 이름이같은 스프라이트 설정 
                    if (rewardslot[j].transform.GetChild(1).GetComponent<Image>().sprite.name != "NONE")//none이 아닐때 활성화 
                    {
                        rewardslot[j].SetActive(true);
                    }
                }
            }
            else if(quest[CharacterManger.instance.questchapter].Progress==true&&quest[CharacterManger.instance.questchapter].isSucess==false)//qeust가 진행중일때 버튼을 진행중으로 보이게 
            {
                progerss.SetActive(true);
           
            questWindow.SetActive(true);
            for (int i = 0; i < button.Length; i++)
            {
                button[i].SetActive(false);
            }
            titleText.text = quest[CharacterManger.instance.questchapter].title;
            descriptionText.text = quest[CharacterManger.instance.questchapter].description;
            for (int j = 0; j < rewardslot.Length; j++)
            {
                rewardslot[j].transform.GetChild(1).GetComponent<Image>().sprite = GameManger.instance.ItemSprite[GameManger.instance.Alltem.FindIndex
                    (x => x.Name == quest[CharacterManger.instance.questchapter].Rewarditems[j].Name)];
                if (rewardslot[j].transform.GetChild(1).GetComponent<Image>().sprite.name != "NONE")
                {
                    rewardslot[j].SetActive(true);
                }
            }
        }
            else if(quest[CharacterManger.instance.questchapter].Progress == true && quest[CharacterManger.instance.questchapter].isSucess == true)//퀘스트가 진행중인데 성공했을때 버튼이 완료로 보이게 설정
        {
            questWindow.SetActive(true);
            for (int i = 0; i < button.Length; i++)
            {
                button[i].SetActive(false);
            }
            progerss.SetActive(false);
            sucess.SetActive(true);
            sucess.GetComponentInChildren<Text>().text = "완료";

        }
            
        }

    public void Sucess()//퀘스트 완료후 보상받을때 
    {
        questWindow.SetActive(false);
        for(int i=0;i<rewardslot.Length;i++)
        {
            Item item = GameManger.instance.Alltem.Find(x => x.Name == quest[CharacterManger.instance.questchapter].Rewarditems[i].Name);//allitem에서 이름이같은 아이템을 찾아서 item에 넣고
            GameManger.instance.MyItemList.Add(item);//그 아이템을 myitemlist에 추가 
           

        }
        
        CharacterManger.instance.questchapter += 1;//퀘스트 진행도 1 증가 
    }
       
    
    
}

 

 

2.퀘스트를 주는 NPC한테 넣어줄 스크립트 QUESTGiver 생성 후 넣어주기 

 

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

public class QuestWindow : MonoBehaviour
{
    public GameObject prefab;
    public GameObject QuestlistWindow;
    public void ClickQuestList()//메인 ui 에서 퀘스트 창 열었을때 
    {
        DrawList();// 퀘스트창 그리기 
        QuestlistWindow.SetActive(true);//퀘스트목록  활성화 
    }
    public void ExitButtonclick()//x버튼 클릭시 
    {
        QuestlistWindow.SetActive(false);//퀘스트창 꺼지게 
        DestroyList();// 퀘스트 지워버리기 
    }
  public void DrawList()
    {
        for(int i=0;i<CharacterManger.instance.myquests.Count;i++)
        {
            GameObject go =Instantiate(prefab);//연결된 prefab 을생성후 
            go.transform.parent = this.transform;// 자식의 위치 
            Text Title = transform.GetChild(i).GetComponent<Text>();//제목 text 넣기 
            Text goal = Title.transform.GetChild(0).GetComponent<Text>();//goal text 넣기 
            Text state = goal.transform.GetChild(0).GetComponent<Text>();//진행중인지 완료인지 상태 보기위해 대입 

            Title.text = CharacterManger.instance.myquests[i].title.ToString();// 캐릭터 매니저에 내퀘스트 제목 대입
            goal.text = CharacterManger.instance.myquests[i].goal.ToString();//캐릭터매니저 내퀘스트 골 대입 
            if(CharacterManger.instance.myquests[i].isSucess==false)//캐릭터 매니저 is sucess 여부로 진행중인지 완료인지 파악 
            {
                state.text = "진행중";
            }
            else
            {
                state.text = "완료";
            }
        }
    }
    public void DestroyList()// destroy시키는 함수 
    {
        for (int i = 0; i < transform.childCount; i++)
        {
            Destroy(transform.GetChild(i).gameObject);
        }
    }

}

 

3.퀘스트 창 스크립트 questwindow 생성후 위코드 입력 

 

public void Comunicationbutton()
    {
        for(int i=0;i<CharacterManger.instance.myquests.Count;i++)
        {
            if(CharacterManger.instance.myquests[i].Questgoal.clearnpcid==GetComponentInParent<NpcData>().id)
            {
                CharacterManger.instance.myquests[i].isSucess = true;
            }
        }
    }
    public void AcceptButton()//수락버튼 클릭 
    {
        if(CharacterManger.instance.myquests.Count==0)//캐릭터매니저에 내퀘스트가 하나도없으면 
        {
            CharacterManger.instance.myquests.Add(QuestGiver.instance.quest[CharacterManger.instance.questchapter]);//내퀘스트에 추가 
            QuestGiver.instance.quest[CharacterManger.instance.questchapter].Progress = true;//퀘스트 진행중 ture 
            questwindow.SetActive(false);//퀘스트 창 꺼지게 
            for (int i = 0; i < button.Length; i++)//버튼창 다시보이게 
            {
                button[i].SetActive(true);
            }
        }
        else//아닐경우 
        {
            for (int i = 0; i < CharacterManger.instance.myquests.Count; i++)
            {
                if (CharacterManger.instance.myquests[i].goal == QuestGiver.instance.quest[CharacterManger.instance.questchapter].goal)//이미수락된 퀘스트일경우 
                {
                    //이미 수락된 퀘스트 라는 팝업 or 그냥냅두기 
                }

                else//이미수락된 퀘스트가 아닐경우  근데 이미 진행도로 퀘스트를 받기 때문에 상관없을코드
                {
                    CharacterManger.instance.myquests.Add(QuestGiver.instance.quest[CharacterManger.instance.questchapter]);//내퀘스트에 추가 
                    QuestGiver.instance.quest[CharacterManger.instance.questchapter].Progress = true;//진행중 true 
                    questwindow.SetActive(false);//퀘스트창 꺼지게 
                    for (int j = 0; j < button.Length; j++)//버튼창 다시보이게 
                    {
                        button[j].SetActive(true);
                    }
                    break;
                }
            }
        }
        
       
    }
    public void RejectButton()//거절버튼 클릭 
    {
        questwindow.SetActive(false);//퀘스트창 off 
        for(int i=0;i<button.Length;i++)
        {
            button[i].SetActive(true); //버튼창 on 
        }
        
    }

4. npc trigger 스크립트에 위 3개 코드 추가 

 

  public List<Quest> myquests = null;// 내퀘스트 
    public int questchapter = 0;//퀘스트 진행도

5. 캐릭터 매니저에 위 2개코드 추가 

 

누구든 간편하게 questgiver를 가진상태에서 

 

퀘스트를 생성할수있으며 

 

퀘스트의 타입은 뭔지 comnicatuon 인지 kill인지

kill이라면 몇마리를 잡아야하는지

 

보상설정 및 내용,제목,설명 까지도 설정 가능하게 해놔서

비개발자 분들도 쉽게 퀘스트 추가 가능하게끔 코드를 짜느라 조금 오래걸렸다. 

 

현재는 퀘스트 진행도로 퀘스트를 진행하지만

 

여러 MMORPG나 PCRPG를 보면 퀘스트를 여러개 받고 수행하는 경우도 있기때문에 QUESTID로도 수행가능하게 코드변경가능하다. 

 

 

주말동안 퀘스트를 완성하고싶었고 이제 보스 및 스킬 구현후 간단한 최적화 작업후 포트폴리오는 끝날예정이다. 

 

아마 다음주면 끝날거라 생각된다 . 

유료 에셋을 구매하면 작업속도를 훨씬 줄이고 퀄리티를 올릴 수 있지만 이번작업은 에셋 구매없이 내힘으로 코드를 직접 구현하는데 의미를 두었기때문에 작업이 꽤 걸렸다. 

반응형

'개인프로젝트 3D RPG 개발일지' 카테고리의 다른 글

32.보스구현중(코드리뷰x)  (0) 2022.08.03
31.보스구현  (0) 2022.08.01
29.퀘스트구현  (0) 2022.07.29
28. 퀘스트구현  (0) 2022.07.28
27.퀘스트시스템 구현  (0) 2022.07.27