해결된 질문
작성
·
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
수강해주셔서 감사합니다.
해당 문제는 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일 때 통과하여야 합니다.
감사합니다.
답변 감사합니다!!