인프런 영문 브랜드 로고
인프런 영문 브랜드 로고

인프런 커뮤니티 질문&답변

meltingice31님의 프로필 이미지
meltingice31

작성한 질문수

[유니티 레벨 업!] 모듈식으로 개발하는 퀘스트&업적 시스템

This quest has already been registered

해결된 질문

작성

·

295

0

안녕하세요

좋은 강의 잘 보고 있습니다!

2장의 QuestSystem 부분까지 다 듣고 난 후, 마지막 테스트하는 부분에서

This quest has already been registered. 라는 에러가 나옵니다.

강의를 돌려보면서 스크립트를 다르게 작성한 부분이 있나 확인해봤는데도 도저히 해결되지 않아 글을 작성하게 되었습니다.

 

제가 작성한 스크립트입니다.

<Quest>

public enum QuestState

{

Inactive,

Running,

Complete,

Cancel,

WaitingForCompletion

}

[CreateAssetMenu(menuName = "Quest/Quest", fileName = "Quest_")]

public class Quest : ScriptableObject

{

#region Event

public delegate void TaskSuccessChangedHandler(Quest quest, Task task, int currentSuccess, int prevSuccess);

public delegate void CompletedHandler(Quest quest);

public delegate void CancelHandler(Quest quest);

public delegate void NewTaskGroupHandler(Quest quest, TaskGroup currentTaskGroup, TaskGroup prevTaskGroup);

#endregion

public event TaskSuccessChangedHandler onTaskSuccessChandged;

public event CompletedHandler onCompleted;

public event CancelHandler onCanceled;

public event NewTaskGroupHandler onNewTaskGroup;

public void OnRegister()

{

// Assert는 인자로 들어온 값이 false면 뒤의 문장을 에러로 띄움.(버그검출용)

Debug.Assert(!IsRegistered, "This quest has already been registered.");

foreach (var taskGroup in taskGroups)

{

taskGroup.Setup(this);

foreach (var task in taskGroup.Tasks)

task.onSuccessChanged += OnSuccessChanged;

}

State = QuestState.Running;

CurrentTaskGroup.Start();

}

public Quest Clone()

{

var clone = Instantiate(this);

clone.taskGroups = taskGroups.Select(x => new TaskGroup(x)).ToArray();

return clone;

}

public void ReceiveReport(string category, object target, int successCount)

{

Debug.Assert(!IsRegistered, "This quest has already been registered.");

Debug.Assert(!IsCancel, "This quest has been canceld");

if (IsComplete)

return;

if (CurrentTaskGroup.IsAllTaskComplete)

{

if (currentTaskGroupIndex + 1 == taskGroups.Length)

{

State = QuestState.WaitingForCompletion;

if (useAutoComplete)

Complete();

}

else

{

var prevTasKGroup = taskGroups[currentTaskGroupIndex++];

prevTasKGroup.End();

CurrentTaskGroup.Start();

onNewTaskGroup?.Invoke(this, CurrentTaskGroup, prevTasKGroup);

}

}

else

State = QuestState.Running;

}

public void Complete()

{

CheckIsRunning();

foreach (var taskGroup in taskGroups)

taskGroup.Complete();

State = QuestState.Complete;

foreach (var reward in rewards)

reward.Give(this);

onCompleted?.Invoke(this);

onTaskSuccessChandged = null;

onCompleted = null;

onCanceled = null;

onNewTaskGroup = null;

}

public virtual void Cancel()

{

CheckIsRunning();

Debug.Assert(IsCancelable, "This quest can't be canceled");

State = QuestState.Cancel;

onCanceled?.Invoke(this);

}

private void OnSuccessChanged(Task task, int currentSuccess, int prevSuccess)

=> onTaskSuccessChandged?.Invoke(this,task,currentSuccess, prevSuccess);

[Conditional("UNITY_EDITOR")]

private void CheckIsRunning()

{

Debug.Assert(!IsRegistered, "This quest has already been registered.");

Debug.Assert(!IsCancel, "This quest has been canceld");

Debug.Assert(!IsCompleatable, "This quest had already been completed");

}

}

 

<QuestSystem>

public class QuestSystem : MonoBehaviour

{

#region Events

public delegate void QuestRegisteredHandler(Quest newQuest);

public delegate void QuestCompletedHandler(Quest quest);

public delegate void QuestCanceledHandler(Quest quest);

#endregion

private static QuestSystem instance;

private static bool isApplicationQuitting;

public static QuestSystem Instance

{

get

{

if (!isApplicationQuitting && instance == null)

{

instance = FindObjectOfType<QuestSystem>();

if (instance == null)

{

instance = new GameObject("Quest System").AddComponent<QuestSystem>();

DontDestroyOnLoad(instance.gameObject);

}

}

return instance;

}

}

private void Awake()

{

questDatabase = Resources.Load<QuestDatabase>("QuestDatabase");

achievementDatabase = Resources.Load<QuestDatabase>("AchievementDatabase");

foreach (var achievement in achievementDatabase.Quests)

Register(achievement);

}

public Quest Register(Quest quest)

{

var newQuest = quest.Clone();

if (newQuest is Achievement)

{

newQuest.onCompleted += OnAchievementCompleted;

activeAchievements.Add(newQuest);

newQuest.OnRegister();

onAchievementRegistered?.Invoke(newQuest);

}

else

{

newQuest.onCompleted += OnQuestCompleted;

newQuest.onCanceled += OnQuestCanceled;

activeQuests.Add(newQuest);

newQuest.OnRegister();

onQuestRegistered?.Invoke(newQuest);

}

return newQuest;

}

public void ReceiveReport(string category, object target, int successCount)

{

ReceiveReport(activeQuests, category, target, successCount);

ReceiveReport(activeAchievements, category, target, successCount);

}

public void ReceiveReport(Category category, TaskTarget target, int successCount)

=> ReceiveReport(category.CodeName, target.Value, successCount);

public bool CantainsInActiveQuests(Quest quest) => activeQuests.Any(x => x.CodeName == quest.CodeName);

public bool CantainsInCompletedQuests(Quest quest) => completedQuests.Any(x => x.CodeName == quest.CodeName);

public bool CantainsInActiveAchievements(Quest quest) => activeAchievements.Any(x => x.CodeName == quest.CodeName);

public bool CantainsInCompletedAchievements(Quest quest) => completedAchievement.Any(x => x.CodeName == quest.CodeName);

private void ReceiveReport(List<Quest> quests, string category, object target, int successCount)

{

foreach (var quest in quests.ToArray())

quest.ReceiveReport(category, target, successCount);

}

#region Callback

private void OnQuestCompleted(Quest quest)

{

activeQuests.Remove(quest);

completedQuests.Add(quest);

onQuestCompleted?.Invoke(quest);

}

private void OnQuestCanceled(Quest quest)

{

activeQuests.Remove(quest);

onQuestCanceled?.Invoke(quest);

Destroy(quest, Time.deltaTime);

}

private void OnAchievementCompleted(Quest achievement)

{

activeAchievements.Remove(achievement);

completedAchievement.Add(achievement);

onAchievementCompleted?.Invoke(achievement);

}

#endregion

}

 

파일을 따로 올리는 곳이 없어 어쩔 수 없이 스크립트 전체를 올렸고 너무 길어서 변수 부분은 생략했습니다!

감사합니다.

 

 

답변 1

1

Developer G님의 프로필 이미지
Developer G
지식공유자

수강해주셔서 감사합니다.

해당 문제는 ReceiveReport 함수의 첫 줄인
Debug.Assert(!IsRegistered, "This quest has already been registered.");를
Debug.Assert(IsRegistered, "This quest has already been registered.")로 바꿔주시면 됩니다.
(! 제거)

ReceiveReport는 Quest가 Register 됐을 때만 동작해야하므로 Asset문을 IsRegistered가 true일 때 통과하여야 합니다.

감사합니다.

meltingice31님의 프로필 이미지
meltingice31
질문자

답변 감사합니다!!

meltingice31님의 프로필 이미지
meltingice31

작성한 질문수

질문하기