Unity

유니티 퀘스트 설계 아이디어 (ScriptableObject)

우대비 2024. 7. 7. 22:01
반응형

퀘스트는 정말 여러 유형이 있습니다.

기본적인 몬스터 사냥, 아이템 획득, NPC와 대화 퀘스트 뿐만 아니라

강화를 몇번 하라는 퀘스트, 인벤토리를 열어보라는 퀘스트, 공격을 해보라는 퀘스트 등

상상도 못할만큼 많은 종류의 퀘스트가 있습니다.

 

이러한 모든 종류의 퀘스트에 대해서 script를 작성하고

퀘스트를 이행했는지 하나하나 체크한다면 굉장히 복잡하고

script를 설계하는 부분에 있어서 굉장히 어려울 것 입니다.

 

하지만 퀘스트를 만드는 것을 반대로 생각해보면 접근이 굉장히 쉽습니다.

각 퀘스트에 id를 부여하고 해당 동작(강화, 인벤토리 오픈 등)이 실행될 때 퀘스트 매니저에 실행을 알립니다.

그러면 퀘스트 매니저에서 해당 id를 가진 퀘스트를 찾고 업데이트(횟수를 ++)해주면

퀘스트별 script를 따로 작성할 필요 없이 간단하게 관리할 수 있게됩니다.

 

 

ScriptableObject

저는 Unity의 scriptableObject를 사용했습니다.

scriptableObejct는 C# Script를 Object로 사용할 수 있는, 게임 데이터와 설정 구성 정보를 

저장하고 관리하는 데 사용되는 기능입니다.

 

JustKnight/Assets/Scripts/Quest/QuestSO.cs at main · znlsnel/JustKnight

2D Unity Project. Contribute to znlsnel/JustKnight development by creating an account on GitHub.

github.com

[CreateAssetMenu(fileName = "NewQuest", menuName = "new Quest", order = 1)]
public class QuestSO : ScriptableObject
{
	public string codeName;
	public string displayName;

	[TextArea(3, 10)]
	public string description;
	public QuestTaskSO task;
    
	public RewardSO reward;
	public bool isCancelable;
	public bool isSavable; 
}

이런식으로 script를 작성하면

해당 script를 하나의 object처럼 사용할 수 있습니다.

(이름과 설명, task, 보상등만 바꾸면 퀘스트가 완성됩니다)

 

 

 

JustKnight/Assets/Scripts/Quest/Task/QuestTaskSO.cs at main · znlsnel/JustKnight

2D Unity Project. Contribute to znlsnel/JustKnight development by creating an account on GitHub.

github.com

[CreateAssetMenu(fileName = "NewQuest", menuName = "Quest/Task", order = 1)]
public class QuestTaskSO : ScriptableObject
{
	public CategorySO category;
	public string displayName;

	[TextArea(3, 10)]
	public string description;

	public TaskActionSO action;
	public TargetSO target;
	 
	public int targetCnt;
	[NonSerialized] public int curCnt = 0;
}

 

Task에는 Category와 Target이 있습니다.

스켈레톤을 20마리 잡는 퀘스트의 경우 Category는 사냥 Target은 스켈레톤 targetCnt는 20이 됩니다.

 

이때 스켈레톤이 죽을 때 해당 Category, Target을 퀘스트 매니저에 보내고

해당 카테고리와 타겟에 해당되는 퀘스트를 받아서 데이터를 새로 업데이트해주면 됩니다. 

 

 

JustKnight/Assets/Scripts/Quest/QuestManager.cs at main · znlsnel/JustKnight

2D Unity Project. Contribute to znlsnel/JustKnight development by creating an account on GitHub.

github.com

 

 

QuestSO quest = QuestManager.instance.GetQuest(category, target);
if (quest != null )
{ 
    quest.task.action.Run(quest.task.curCnt, successCount);

    if (quest.task.curCnt >= quest.task.targetCnt)
    { 
        quest.reward.Get();
    }
}

이런식으로 퀘스트에 포함된 보상을 받으면 퀘스트가 종료되는 것 까지 쉽게 관리가 가능합니다.

 

정리해보자면 이렇습니다.

scriptableObejct 생성 후 퀘스트 정보를 입력합니다.

퀘스트의 Task부분에는 해당 Task의 Category와 Target을 넣어줍니다.

(이때 Category와 Target은 찾는 용도이기에 String으로 만들어도 전혀 상관없습니다)

 

그리고 해당 퀘스트의 동작이 실행되는 타이밍에

카테고리와 타겟이 해당되는 퀘스트를 퀘스트 매니저에게 요청하고

퀘스트를 새로 업데이트 해줍니다.

 

만약 퀘스트가 완료되었다면 보상을 받아 종료할 수도 있습니다.

보상은 NPC에게 돌아가서 받는 로직을 설계할 수도 있겠네요

 

핵심은 퀘스트의 진행 상황을 script에서 찾는게 아니라 script에 보고하는 것 입니다.

감사합니다.

 

 

 

 

 

반응형
LIST

'Unity' 카테고리의 다른 글

Google Sign in Plugin 임포트시 발생하는 에러 해결법  (1) 2024.12.17
유니티 구글 플레이 업적 시스템, 리더 보드  (0) 2024.10.27
Unity Instantiate  (1) 2024.06.11
Unity JsonUtility  (0) 2024.05.31
Input Action Asset  (0) 2024.05.30