From 943178cbc10ed32a177b067298dbf10ad4c0c983 Mon Sep 17 00:00:00 2001 From: Joywayer Date: Mon, 25 May 2026 07:20:55 +0800 Subject: [PATCH] fix: Round 54 priority dequeue, onComplete callback, prerequisiteObjectiveId validation, localizationTable guard, FailQuest timestamp, remove empty ValidateBranchDialogueKeys - DialogueManager.EndDialogue: dequeue by max-priority index instead of FIFO index-0 - DialogueManager.EndDialogue: fire _onCompleteCallback on normal end (was only in ForceEnd) - NpcSO.OnValidate: auto-restore localizationTable to 'UI' if cleared - QuestSO.ValidateObjectiveIds: validate prerequisiteObjectiveId references exist in same quest - QuestSO.OnValidate: remove call to empty ValidateBranchDialogueKeys stub + remove the stub itself - QuestManager.DispatchEvent toFail loop: write _completedAtUtc timestamp on quest failure Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../_Game/Scripts/Dialogue/DialogueManager.cs | 14 +++++++++++--- Assets/_Game/Scripts/Dialogue/NpcSO.cs | 3 +++ Assets/_Game/Scripts/Quest/QuestManager.cs | 1 + Assets/_Game/Scripts/Quest/QuestSO.cs | 17 +++++++++++------ 4 files changed, 26 insertions(+), 9 deletions(-) diff --git a/Assets/_Game/Scripts/Dialogue/DialogueManager.cs b/Assets/_Game/Scripts/Dialogue/DialogueManager.cs index c745572..6f465c1 100644 --- a/Assets/_Game/Scripts/Dialogue/DialogueManager.cs +++ b/Assets/_Game/Scripts/Dialogue/DialogueManager.cs @@ -432,11 +432,19 @@ namespace BaseGames.Dialogue if (!string.IsNullOrEmpty(npcId)) _onNpcDialogueCompleted?.Raise(npcId); - // 自动播放队首等待中的对话(脚本触发的连续序列) + // 触发一次性完成回调(正常结束和强制中断均触发) + var cb = _onCompleteCallback; + _onCompleteCallback = null; + cb?.Invoke(); + + // 自动播放优先级最高的等待中对话(保证高优先级对话不被低优先级插队) if (_pending.Count > 0) { - var item = _pending[0]; - _pending.RemoveAt(0); + int best = 0; + for (int i = 1; i < _pending.Count; i++) + if (_pending[i].priority > _pending[best].priority) best = i; + var item = _pending[best]; + _pending.RemoveAt(best); PlayImmediate(item.seq, item.npcId, item.priority); } } diff --git a/Assets/_Game/Scripts/Dialogue/NpcSO.cs b/Assets/_Game/Scripts/Dialogue/NpcSO.cs index 3114095..0f6652b 100644 --- a/Assets/_Game/Scripts/Dialogue/NpcSO.cs +++ b/Assets/_Game/Scripts/Dialogue/NpcSO.cs @@ -68,6 +68,9 @@ namespace BaseGames.Dialogue private void OnValidate() { + if (string.IsNullOrEmpty(localizationTable)) + localizationTable = "UI"; + if (string.IsNullOrWhiteSpace(npcId)) { UnityEditor.EditorUtility.SetDirty(this); diff --git a/Assets/_Game/Scripts/Quest/QuestManager.cs b/Assets/_Game/Scripts/Quest/QuestManager.cs index 0eaf105..3d09ad8 100644 --- a/Assets/_Game/Scripts/Quest/QuestManager.cs +++ b/Assets/_Game/Scripts/Quest/QuestManager.cs @@ -1014,6 +1014,7 @@ namespace BaseGames.Quest foreach (var qid in toFail) { _questStates[qid] = QuestStateEnum.Failed; + _completedAtUtc[qid] = System.DateTimeOffset.UtcNow.ToUnixTimeSeconds(); _notifiedReadyQuests.Remove(qid); OnQuestStateChanged?.Invoke(qid, QuestStateEnum.Active, QuestStateEnum.Failed); Chan_QuestFailed?.Raise(qid); diff --git a/Assets/_Game/Scripts/Quest/QuestSO.cs b/Assets/_Game/Scripts/Quest/QuestSO.cs index 6914d9c..0fc0c8d 100644 --- a/Assets/_Game/Scripts/Quest/QuestSO.cs +++ b/Assets/_Game/Scripts/Quest/QuestSO.cs @@ -118,7 +118,6 @@ namespace BaseGames.Quest s_questIdsCacheTime = -10.0; } - ValidateBranchDialogueKeys(); ValidateObjectiveIds(); ValidatePrerequisiteCycles(); ValidateBranchCycles(); @@ -138,6 +137,17 @@ namespace BaseGames.Quest "在本任务内重复!同一个 ObjectiveSO 资产被引用多次会导致进度互相覆盖," + "请为每个目标使用独立的 SO 资产。", this); } + + // 验证 prerequisiteObjectiveId 引用的 objectiveId 必须存在于本任务中 + for (int i = 0; i < objectives.Length; i++) + { + var obj = objectives[i]; + if (obj == null || string.IsNullOrEmpty(obj.prerequisiteObjectiveId)) continue; + if (!seen.Contains(obj.prerequisiteObjectiveId)) + Debug.LogError( + $"[QuestSO] '{name}' 的 objectives[{i}].prerequisiteObjectiveId " + + $"'{obj.prerequisiteObjectiveId}' 在本任务中不存在!请检查目标ID是否填写正确。", this); + } } /// @@ -249,11 +259,6 @@ namespace BaseGames.Quest visited.Remove(quest.questId); // 回溯 return false; } - - private void ValidateBranchDialogueKeys() - { - // npcDialogueSequence 是 SO 直接引用;旧字符串字段已移除。 - } #endif }