feat: Round 48 narrative systems improvements
- QuestSO: Add ValidateBranchCycles() DFS detection for branches[].nextQuest loop - QuestSO: Mark three legacy prerequisite fields with v2.0 removal warning in Tooltip - IQuestManager: Add QuestLockReason enum + QuestLockInfo struct (strongly-typed lock info) - IQuestManager: Add GetQuestLockInfo() method to interface; GetQuestLockReason() now delegates to it - IQuestEventSource: Add OnQuestStateChanged(questId, oldState, newState) unified event - QuestManager: Implement GetQuestLockInfo(); fire OnQuestStateChanged on all state transitions - DialogueManager: Add one-frame yield in HandleChoices before ShowChoices (skip-debounce fix) - DialogueManager: Increment _playbackId in ForceEnd() to invalidate residual choice callbacks - DialogueSequenceSO: Add UNITY_EDITOR debug log in TryGetActiveVariant on variant match - WorldStateRegistry: Add OnBatchStateChanged event + BatchMark() batch-write API - DialogueModule: List badge shows warning indicator for unconditional-shadowing variants - DialogueModule: BuildVariantsCard shows logic mode (AND/OR) alongside flag conditions Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 832e6ad6d64454d4286183c6d7cfdc3e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
118
Assets/_Game/Scripts/Editor/Quest/QuestSOEditor.cs
Normal file
118
Assets/_Game/Scripts/Editor/Quest/QuestSOEditor.cs
Normal file
@@ -0,0 +1,118 @@
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using BaseGames.Quest;
|
||||
using BaseGames.Core;
|
||||
|
||||
namespace BaseGames.Editor.Quest
|
||||
{
|
||||
/// <summary>
|
||||
/// QuestSO 自定义 Inspector。
|
||||
/// 在检测到旧版前置字段(prerequisiteQuests / prerequisiteFlags)有数据时,
|
||||
/// 显示迁移提示框和一键迁移按钮,引导策划将数据迁移到 QuestPrerequisite 统一结构。
|
||||
/// </summary>
|
||||
[CustomEditor(typeof(QuestSO))]
|
||||
public class QuestSOEditor : UnityEditor.Editor
|
||||
{
|
||||
private bool _showMigrationBox = true;
|
||||
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
serializedObject.Update();
|
||||
|
||||
var quest = (QuestSO)target;
|
||||
|
||||
// ── 旧版字段迁移提示 ──────────────────────────────────────────────
|
||||
#pragma warning disable CS0618
|
||||
bool hasLegacyQuests = quest.prerequisiteQuests != null && quest.prerequisiteQuests.Length > 0;
|
||||
bool hasLegacyFlags = quest.prerequisiteFlags != null && quest.prerequisiteFlags.Length > 0;
|
||||
#pragma warning restore CS0618
|
||||
|
||||
if (hasLegacyQuests || hasLegacyFlags)
|
||||
{
|
||||
_showMigrationBox = EditorGUILayout.BeginFoldoutHeaderGroup(_showMigrationBox, "⚠ 旧版前置字段迁移");
|
||||
if (_showMigrationBox)
|
||||
{
|
||||
EditorGUILayout.HelpBox(
|
||||
"检测到旧版前置字段有数据:\n" +
|
||||
(hasLegacyQuests ? $" • prerequisiteQuests:{quest.prerequisiteQuests.Length} 项\n" : "") +
|
||||
(hasLegacyFlags ? $" • prerequisiteFlags:{quest.prerequisiteFlags.Length} 项\n" : "") +
|
||||
"\n新版 'prerequisites'(QuestPrerequisite)字段已支持更完整的前置配置。\n" +
|
||||
"点击下方按钮可将旧版数据自动迁移至新字段,迁移后旧字段将被清空。\n" +
|
||||
"迁移操作可撤销(Ctrl+Z)。",
|
||||
MessageType.Warning);
|
||||
|
||||
bool hasNewData = quest.prerequisites.HasAny;
|
||||
if (hasNewData)
|
||||
EditorGUILayout.HelpBox(
|
||||
"新版 prerequisites 字段已有数据。点击迁移将与旧版数据合并(去重),不会覆盖现有配置。",
|
||||
MessageType.Info);
|
||||
|
||||
if (GUILayout.Button("一键迁移旧版前置字段 → prerequisites"))
|
||||
{
|
||||
MigrateLegacyPrerequisites(quest);
|
||||
}
|
||||
}
|
||||
EditorGUILayout.EndFoldoutHeaderGroup();
|
||||
EditorGUILayout.Space(4);
|
||||
}
|
||||
|
||||
// ── 默认 Inspector ────────────────────────────────────────────────
|
||||
DrawDefaultInspector();
|
||||
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
|
||||
private static void MigrateLegacyPrerequisites(QuestSO quest)
|
||||
{
|
||||
Undo.RecordObject(quest, "迁移 QuestSO 旧版前置字段");
|
||||
|
||||
#pragma warning disable CS0618
|
||||
int legacyQuestCount = quest.prerequisiteQuests?.Length ?? 0;
|
||||
int legacyFlagCount = quest.prerequisiteFlags?.Length ?? 0;
|
||||
|
||||
// 迁移 prerequisiteQuests → prerequisites.questDependencies(合并去重)
|
||||
if (quest.prerequisiteQuests != null && quest.prerequisiteQuests.Length > 0)
|
||||
{
|
||||
var existing = quest.prerequisites.questDependencies ?? System.Array.Empty<QuestSO>();
|
||||
var merged = new System.Collections.Generic.HashSet<QuestSO>(existing);
|
||||
foreach (var q in quest.prerequisiteQuests)
|
||||
if (q != null) merged.Add(q);
|
||||
|
||||
quest.prerequisites.questDependencies = new QuestSO[merged.Count];
|
||||
merged.CopyTo(quest.prerequisites.questDependencies);
|
||||
quest.prerequisiteQuests = System.Array.Empty<QuestSO>();
|
||||
}
|
||||
|
||||
// 迁移 prerequisiteFlags → prerequisites.flagCondition(合并去重)
|
||||
if (quest.prerequisiteFlags != null && quest.prerequisiteFlags.Length > 0)
|
||||
{
|
||||
var existing = quest.prerequisites.flagCondition.flags ?? System.Array.Empty<string>();
|
||||
var merged = new System.Collections.Generic.HashSet<string>(
|
||||
existing, System.StringComparer.Ordinal);
|
||||
foreach (var f in quest.prerequisiteFlags)
|
||||
if (!string.IsNullOrEmpty(f)) merged.Add(f);
|
||||
|
||||
quest.prerequisites.flagCondition.flags = new string[merged.Count];
|
||||
merged.CopyTo(quest.prerequisites.flagCondition.flags);
|
||||
// 迁移逻辑模式(旧字段覆盖新字段,以旧配置为准)
|
||||
quest.prerequisites.flagCondition.logic = quest.prerequisiteFlagsLogic;
|
||||
|
||||
quest.prerequisiteFlags = System.Array.Empty<string>();
|
||||
quest.prerequisiteFlagsLogic = WorldStateFlagLogic.And;
|
||||
}
|
||||
#pragma warning restore CS0618
|
||||
|
||||
EditorUtility.SetDirty(quest);
|
||||
AssetDatabase.SaveAssets();
|
||||
|
||||
Debug.Log($"[QuestSOEditor] '{quest.name}' 旧版前置字段迁移完成(任务:{legacyQuestCount} 项,标志:{legacyFlagCount} 项)。", quest);
|
||||
EditorUtility.DisplayDialog(
|
||||
"迁移完成",
|
||||
$"任务 \"{quest.name}\" 旧版前置字段已成功迁移:\n\n" +
|
||||
$" 前置任务:{legacyQuestCount} 项 → prerequisites.questDependencies\n" +
|
||||
$" 前置标志:{legacyFlagCount} 项 → prerequisites.flagCondition.flags\n\n" +
|
||||
"旧版字段已清空。操作可通过 Ctrl+Z 撤销。",
|
||||
"确定");
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user