미로스 - 4. 퀘스트나 미션등의 요소를 기획하여 게임 플레이 이벤트를 설계 구현, 결과에 대한 보상성 포함
- 100 powerun
- 2024년 11월 27일
- 3분 분량
최종 수정일: 2월 13일
퀘스트는 다음 아래와 같은 부모 클래스를 사용합니다.
부모 클래스는 스크립터블 오브젝트로 생성되며 이후 enum Type에 따라 자식 class를 생성하여 세부 분류로 나뉘게 됩니다.
public enum Type
{
Find = 0,
Hunt,
Talk,
Arrive
};
public enum RewardType
{
Item=0,
Money
};
[Tooltip("퀘스트 타입분류")]
public Type type;
[Tooltip("보상 타입분류")]
public RewardType rewardType;
[Tooltip("보상 아이템, 보상타입이 아이템일 경우에만 적용됨")]
public ItemObject rewardItem;
[Tooltip("보상 수량")]
public int rewardQuantity;
[TextArea,Tooltip("퀘스트 타이틀")]
public string questTitle;
[TextArea, Tooltip("퀘스트 타이틀")]
public string texts;
[TextArea, Tooltip("퀘스트 진행창에 표시될 텍스트")]
public string request;
public abstract void QuestStart();
/// <summary>
/// 퀘스트 클리어 가상화 함수
/// 내용 : 공통 보상처리
/// </summary>
public virtual void Clear()
{
Debug.Log("퀘스트 클리어~~~~");
QuestManager.instance.ClearQuest(int.Parse(this.name.Substring(0,1)));
switch (rewardType)
{
case RewardType.Item:
{
if (rewardItem != null)
{
InventoryManager.Instance.ObtainItem(rewardItem, rewardQuantity);
}
//GameObject.Find("Player").GetComponent<PlayerInventory>().inventory[rewardItem.itemtype].ObtainItem(rewardItem, 1);
break;
}
case RewardType.Money:
{
//재화 보상처리
Managers.Game.Gold += rewardQuantity;
break;
}
}
}
스크립터블 오브젝트로 생성하는 만큼 우선 퀘스트라면 기본적으로 들어가야 할 요소들을 넣을 수 있게 만듭니다. 주된 요소로는 퀘스트 타이틀, 내용, 퀘스트 진행 창에 나타날 이름, 보상 처리등이 있습니다. 이곳에서의 보상 처리는 아이템과 재화 총 2가지의 보상 방식이 있습니다.

스크립터블 오브젝트로 생성된 퀘스트는 인스팩터에서 세부 사항을 수정하거나 추가할 수 있습니다.
퀘스트 수행의 예시로 사냥을 들어보자면
public class HuntQuest : Quest
{
public int monsterId = 0;
public int huntGoal;
public int curHuntCnt=0;
public override void Clear()
{
base.Clear();
//특수보상 처리
}
public void KillMonster(int id)
{
if (monsterId == id)
{
curHuntCnt++;
QuestManager.instance.questWindow.GetComponent<CurrentQuestWindow>().CheckQuest(this);
if (huntGoal == curHuntCnt)
{
this.Clear();
}
}
}
public override void QuestStart()
{
curHuntCnt = 0;
}
}
이 게임내에 있는 모든 몬스터들은 퀘스트와 관련된 ID값을 가지는데 만약 플레이어가 몬스터를 잡았을 때 해당 ID가 몬스터와 일치한다면 카운트를 증가시키게 됩니다.
맨 아래의 퀘스트 스타트는 퀘스트를 처음 받았을 때 퀘스트가 이전 진행 상황과 겹치지 않도록 0으로 초기화 시켜주는 역할을 합니다.

맨 아래에 id를 생성한것이 보이는데 이 id가 해당 몬스터를 쓰러트렸을 때 쌓이게 되며 이 id를 가진 몬스터를 특정수를 처치하게 되면 퀘스트가 클리어 되는 방식입니다.
public void KillMonster(int id)
{
if (monsterId == id)
{
curHuntCnt++;
QuestManager.instance.questWindow.GetComponent<CurrentQuestWindow>().CheckQuest(this);
if (huntGoal == curHuntCnt)
{
this.Clear();
}
}
}
이곳이 바로 몬스터의 id를 파악하는 곳으로, 만약 조건이 맞는다면 CurrentQuestWindow에서 현재 퀘스트의 진행도를 갱신 시킵니다.
public class CurrentQuestWindow : MonoBehaviour
{
private GridLayoutGroup glg;
public GameObject questSlot;
List<GameObject> slots = new List<GameObject>();
private void Awake()
{
glg = GetComponent<GridLayoutGroup>();
}
public void AddQuest(Quest quest)
{
Debug.Log("addCheck");
GameObject slot = Instantiate(questSlot);
slot.transform.parent = this.transform;
slots.Add(slot);
slot.GetComponent<Qslot>().SetTitle(quest.questTitle);
slot.GetComponent<Qslot>().SetRequest(quest.request);
slot.GetComponent<Qslot>().quest = quest;
CheckQuest(quest);
}
public void CheckQuest(Quest quest)
{
GameObject slot = null;
for (int i = 0; i < slots.Count; i++)
{
if (slots[i].GetComponent<Qslot>().quest == quest)
{
slot = slots[i];
break;
}
}
if (slot== null) return;
if (quest.type == Quest.Type.Hunt)
{
HuntQuest q = (HuntQuest)quest;
slot.GetComponent<Qslot>().current.text = q.curHuntCnt + " / " + q.huntGoal;
}
else
{
slot.GetComponent<Qslot>().current.text ="";
}
}
public void ClearQuest(Quest quest){
for (int i = 0; i < slots.Count; i++)
{
if (slots[i].GetComponent<Qslot>().quest == quest)
{
Destroy(slots[i].gameObject);
slots.RemoveAt(i);
return;
}
}
}
}
위에는 수락한 퀘스트를 관리하는 스크립트로 퀘스트를 승낙하였을 때 AddQuest로 현재 진행중인 퀘스트를 추가합니다. 아래의 Qslot들은 모두 캔버스와 관련된 스크립트 입니다. 이후 퀘스트를 진행하는것은 위의 HunQuest에 있던 KillMonster안의 CheckQuest에서 관리하게 되는데
if (quest.type == Quest.Type.Hunt)
{
HuntQuest q = (HuntQuest)quest;
slot.GetComponent<Qslot>().current.text = q.curHuntCnt + " / " + q.huntGoal;
}
만약 퀘스트의 종류가 사냥이라면 오른쪽에 사냥해야하는 몬스터 표시와 처치한 몬스터를 표시하는 캔버스 작업과 캔버스를 불러오기 전 퀘스트의 정보를 가져오는 변수로 이루어져 있습니다.

몬스터 잡기 전

몬스터를 잡은 후
시연 영상에서도 설명했 듯 구현한 시스템의 한계로 퀘스트 완료시 보상이 자동으로 들어오는구조로 되여있습니다.
Kommentare