
오늘은 대화창의 선택에 따라 퀘스트가 진행되도록 만들어보자
우선 퀘스트를 하나 만들어줘야한다. 퀘스트는 Scriptable Object로 만들어서 관리해주도록 하자.
클래스위에 Create를 쉽게 할 수 있도록 메뉴에서 선택가능하도록 메뉴에 추가해주는 코드를 추가해줬다.
QuestData.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[CreateAssetMenu(fileName = "NewQuest", menuName = "Quest/QuestData")]
public class QuestData : ScriptableObject
{
[Header("Quest Info")]
public string questName;
public int questId; //퀘스트번호
public QuestState questState; //퀘스트 상태
public int QuestIndex; //퀘스트 필요인덱스
public string location;
[Header("Reward Info")]
public int goldReward;
}
이 QuestData를 관리해주는 Manager를 만들어주자. 퀘스트를 Resource에서 가져오고 Quest의 상태를 Update하고 QuestData를 반환해주는 함수도 추가해주자.
QuestManager.cs
using System.Collections.Generic;
using UnityEngine;
public class QuestManager : MonoBehaviour
{
[SerializeField] private Dictionary<int, QuestData> Quests;
public void Init()
{
LoadQuestsFromResources();
InitializeQuest();
}
// Resources 폴더에서 모든 ScriptableObject를 로드하고 Dictionary로 초기화
private void LoadQuestsFromResources()
{
QuestData[] loadedQuests = Resources.LoadAll<QuestData>("Quest");
Quests = new Dictionary<int, QuestData>();
if (loadedQuests.Length == 0)
{
Debug.LogError("Resources/Quest 폴더에 퀘스트 데이터가 없습니다.");
return;
}
foreach (QuestData questData in loadedQuests)
{
if (!Quests.ContainsKey(questData.questId))
{
Quests.Add(questData.questId, questData);
Debug.Log($"퀘스트 Id '{questData.questId}' 인 '{questData.questName}'가 추가되었습니다.");
}
else
{
Debug.LogWarning($"중복된 questId({questData.questId})가 발견되었습니다. QuestName: {questData.questName}");
}
}
Debug.Log($"{Quests.Count}개의 퀘스트가 로드되었습니다.");
}
// Dictionary를 사용하여 퀘스트를 초기화
private void InitializeQuest()
{
if (Quests == null || Quests.Count == 0)
{
Debug.LogError("Quests가 null이거나 비어 있습니다. LoadQuestsFromResources를 확인하세요.");
return;
}
foreach (var questData in Quests.Values)
{
if (questData.QuestIndex >= Managers.Game.GetPlayer().GetComponent<Player>().index &&
questData.questState == QuestState.REQUIREMENTS_NOT_MET)
{
// 진행 가능한 상태로 변경
questData.questState = QuestState.CAN_START;
Debug.Log($"퀘스트 Id '{questData.questId}' 인 '{questData.questName}'가 CAN_START로 초기화되었습니다.");
}
}
}
// 퀘스트 상태를 업데이트
public void UpdateQuest(int questId)
{
if (Quests.TryGetValue(questId, out QuestData questData))
{
questData.questState++;
if (questData.questState == QuestState.CAN_START)
{
Debug.Log($"퀘스트 시작! QuestName: {questData.questName}");
}
else if (questData.questState == QuestState.CAN_FINISH)
{
Debug.Log($"퀘스트 완료 가능! QuestName: {questData.questName}");
}
else if (questData.questState == QuestState.FINISHED)
{
Debug.Log($"퀘스트 완료! QuestName: {questData.questName}");
Managers.Game.GetPlayer().GetComponent<Player>().index++;
InitializeQuest();
}
}
else
{
Debug.LogError($"questId({questId})에 해당하는 퀘스트가 없습니다.");
}
}
// questId로 퀘스트 데이터를 가져옴
public QuestData GetQuestData(int questId)
{
foreach (var questData in Quests.Values)
{
Debug.Log(questData.name);
if (questData.questId == questId) return questData;
}
return null;
}
}
이렇게 해주고 간단한 퀘스트를 추가해서 이 매니저가 작동하는지 확인해주자

우선 퀘스트를 가져오는 것은 성공했다.
이제 대화에서 선택했을 때 퀘스트의 진행상황이 바뀌는지 확인하자. 이를 위해 DialogueManager의 Tag관리 코드를 수정해주자.
DialogueManager.cs
private const string QuestTag = "Quest"; //테그값들 테그값 : 변수
private const string ChooseTag = "Start";
private const string EndTag = "End";
public void ContinueStory()
{
if (currentStory == null) // Null 체크 추가
{
Debug.LogError("currentStory가 null입니다!");
return;
}
if (currentStory.canContinue) // 더 보여줄 이야기가 있다면
{
popup.displayNameText.text = npcdata.getName();
popup.portraitImage.sprite = npcdata.getPortrait();
popup.dialogueText.text = currentStory.Continue(); // 한줄 출력
DisplayChoices(); // 선택이 있으면 선택 출력
HandleTags(currentStory.currentTags);
}
else
{
ExitDialogueMode();
}
}
private void HandleTags(List<string> currentTags)
{
foreach (string tag in currentTags)
{
string[] splitTag = tag.Split(':');
if (splitTag.Length != 2)
{
Debug.LogError("Tag parsed error : " + tag + splitTag);
}
string tagkey = splitTag[0].Trim();
string tagvalue = splitTag[1].Trim();
switch (tagkey)
{
case QuestTag:
currentQuestIndex = int.Parse(tagvalue);
break;
case ChooseTag:
if (tagvalue =="1")
{
Managers.Quest.UpdateQuest(currentQuestIndex);
Debug.Log("Update!"+Managers.Quest.GetQuestData(currentQuestIndex).questState);
}
break;
case EndTag:
if(tagvalue =="1")
{
Managers.Quest.UpdateQuest(currentQuestIndex);
Debug.Log("Update!" + Managers.Quest.GetQuestData(currentQuestIndex).questState);
}
break;
default:
Debug.LogWarning("Tag exists but not handled");
break;
}
}
}
이렇게 해주고 대화를 하나 만들어주자.
Sori1.ink

이렇게 해주고 테스트해보자.



정상적으로 작동하는 것을 볼 수 있다.
'게임공부 > Unity' 카테고리의 다른 글
[C#][Unity][나만의 탑뷰 게임 만들기]5. 저장시스템 기초만들기 (1) | 2024.12.22 |
---|---|
[C#][Unity][나만의 탑뷰 게임 만들기]4. 아이템 시스템 만들기 (0) | 2024.12.18 |
[C#][Unity][나만의 탑뷰 게임 만들기]3. 퀘스트시스템 만들기-1 (1) | 2024.11.25 |
[C#][Unity][나만의 탑뷰 게임 만들기]2. 대화 상호작용 만들기 (3) | 2024.11.06 |
[C#][Unity][나만의 탑뷰 게임 만들기]1. 이동 및 타일맵 (2) | 2024.10.04 |