fix: Round 56 亲密度门槛UI、空npcId警告、任务总览窗口、超时缓存、本地化Key检查、放弃任务交互、CurrentNpcId属性
- QuestManager.ApplyAffinity: giverNpc.npcId 为空时改为 LogWarning+return,不再静默丢弃好感度奖励 - QuestManager.UnlockBranches: 分支对话 npcId 为空时输出 LogWarning,提示开发者可能误推进对话类目标 - QuestGiver.InteractPrompt: Available 状态调用 GetQuestLockInfo,亲密度/前置未满足时显示锁定原因而非'接受任务' - QuestGiver.Interact_Internal: Available 状态加锁定检查防卫,锁定时提前返回;新增 _allowAbandon 字段(默认 false) - QuestGiver: Active+未完成+_allowAbandon=true 时显示'放弃任务'并触发 AbandonQuest,接入已有 AbandonQuest 接口 - DialogueManager: 新增 _waitSequenceTimeout 缓存字段,Awake 预创建避免每次 PlayImmediate 分配 WaitForSeconds - DialogueManager: 新增 _currentNpcId 字段,PlayImmediate 写入、EndDialogue/ForceEnd 清空 - IDialogueService + DialogueManager: 暴露 CurrentNpcId 只读属性,供外部系统主动查询当前对话 NPC - QuestSO.OnValidate: 对空 displayNameKey/descriptionKey 输出 LogWarning,防止 UI 显示空文本 - 新增 QuestOverviewEditorWindow: BaseGames/Quest/Quest Overview,列出全部 QuestSO,支持搜索/分类过滤; Play Mode 下读取 IQuestManager 运行时状态并着色显示;Edit Mode 高亮配置错误行;单击 Ping、双击 Select Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -74,6 +74,8 @@ namespace BaseGames.Dialogue
|
||||
private DialogueSequenceSO _choiceBranchResult;
|
||||
/// <summary>HandleChoices 子协程写入结果:true = 分支深度超限,优雅降级(继续播放后续行)。</summary>
|
||||
private bool _branchDepthExceeded;
|
||||
/// <summary>当前正在播放对话的 NPC ID(无对话时为 null)。供外部系统主动查询"谁在说话"。</summary>
|
||||
private string _currentNpcId;
|
||||
|
||||
// ── 复用 Yield 指令,避免协程每行 new WaitUntil 闭包 ───────────────
|
||||
private sealed class WaitTypingOrSkip : CustomYieldInstruction
|
||||
@@ -101,6 +103,8 @@ namespace BaseGames.Dialogue
|
||||
private WaitForChoice _waitForChoice;
|
||||
// 延迟 0.15s 防止玩家快速连击穿透:跳过打字机后立即触发选项0
|
||||
private WaitForSeconds _waitChoiceInputGuard;
|
||||
// 超时守卫等待指令(与 _sequenceTimeoutSeconds 同步,在 Awake 初始化,避免每次 PlayImmediate 分配)
|
||||
private WaitForSeconds _waitSequenceTimeout;
|
||||
|
||||
/// <summary>
|
||||
/// 当 IsDialogueActive 时排队等待的对话请求。
|
||||
@@ -113,6 +117,12 @@ namespace BaseGames.Dialogue
|
||||
/// <summary>当前是否有对话正在播放。</summary>
|
||||
public bool IsDialogueActive { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// 当前正在播放对话的 NPC ID。无对话活跃时为 <see langword="null"/>。
|
||||
/// 供地图标记、HUD、分析埋点等外部系统主动查询"当前谁在说话",无需订阅事件。
|
||||
/// </summary>
|
||||
public string CurrentNpcId => _currentNpcId;
|
||||
|
||||
/// <summary>当前正在播放的对话优先级(0 = 默认)。高优先级请求可打断低优先级。</summary>
|
||||
private int _currentPriority;
|
||||
|
||||
@@ -129,6 +139,8 @@ namespace BaseGames.Dialogue
|
||||
_waitSkip = new WaitSkip(this);
|
||||
_waitForChoice = new WaitForChoice(this);
|
||||
_waitChoiceInputGuard = new WaitForSeconds(0.15f);
|
||||
if (_sequenceTimeoutSeconds > 0f)
|
||||
_waitSequenceTimeout = new WaitForSeconds(_sequenceTimeoutSeconds);
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
@@ -230,6 +242,7 @@ namespace BaseGames.Dialogue
|
||||
private void PlayImmediate(DialogueSequenceSO sequence, string npcId, int priority = 0)
|
||||
{
|
||||
IsDialogueActive = true;
|
||||
_currentNpcId = npcId;
|
||||
_currentPriority = priority;
|
||||
_skipRequested = false;
|
||||
_selectedChoiceIndex = -1;
|
||||
@@ -249,7 +262,7 @@ namespace BaseGames.Dialogue
|
||||
/// </summary>
|
||||
private IEnumerator SequenceTimeoutGuard(string npcId)
|
||||
{
|
||||
yield return new WaitForSeconds(_sequenceTimeoutSeconds);
|
||||
yield return _waitSequenceTimeout ?? new WaitForSeconds(_sequenceTimeoutSeconds);
|
||||
if (!IsDialogueActive) yield break;
|
||||
Debug.LogError(
|
||||
$"[DialogueManager] 对话序列 (npcId='{npcId}') 超时 {_sequenceTimeoutSeconds}s 未结束," +
|
||||
@@ -271,6 +284,7 @@ namespace BaseGames.Dialogue
|
||||
_dialogueBox?.HideChoices();
|
||||
_dialogueBox?.Hide();
|
||||
IsDialogueActive = false;
|
||||
_currentNpcId = null;
|
||||
_currentPriority = 0;
|
||||
_skipRequested = false;
|
||||
_selectedChoiceIndex = -1;
|
||||
@@ -424,6 +438,7 @@ namespace BaseGames.Dialogue
|
||||
{
|
||||
_dialogueBox?.Hide();
|
||||
IsDialogueActive = false;
|
||||
_currentNpcId = null;
|
||||
_currentPriority = 0;
|
||||
|
||||
// 优先通过 _onDialogueEnded 事件让 InputManager 决定如何恢复输入;
|
||||
|
||||
@@ -8,6 +8,12 @@ namespace BaseGames.Dialogue
|
||||
/// <summary>当前是否有对话正在播放。</summary>
|
||||
bool IsDialogueActive { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 当前正在播放对话的 NPC ID。无对话活跃时为 <see langword="null"/>。
|
||||
/// 供地图标记、HUD、分析埋点等外部系统主动查询,无需订阅事件。
|
||||
/// </summary>
|
||||
string CurrentNpcId { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 每次对话序列(含分支链)全部播完后触发。
|
||||
/// 测试代码可订阅此事件等待对话结束,无需依赖 VoidEventChannelSO 资产。
|
||||
|
||||
Reference in New Issue
Block a user