using UnityEngine; using BaseGames.World; namespace BaseGames.Dialogue { /// /// 可交互 NPC 基类(架构 14_NarrativeModule §5)。 /// 实现 IInteractable,触发对话序列;子类(如 QuestGiver)可覆盖对话选择逻辑。 /// 程序集: BaseGames.Dialogue /// public class InteractableNPC : MonoBehaviour, IInteractable { [SerializeField] protected string _npcId; [SerializeField] protected DialogueSequenceSO _defaultDialogue; [SerializeField] protected float _interactRadius = 1.5f; // ── IInteractable ────────────────────────────────────────────────── public virtual bool CanInteract => true; public virtual string InteractPrompt => "对话"; public void Interact(Transform player) { if (!CanInteract) return; Interact_Internal(player); var dialogue = GetCurrentDialogue(); if (dialogue != null) PlayDialogue(dialogue, player); } public virtual void OnPlayerEnterRange(Transform player) { } public virtual void OnPlayerExitRange() { } // ── 子类覆盖点 ────────────────────────────────────────────────────── /// 交互前置逻辑(如任务接收/完成判断)。子类覆盖此方法。 protected virtual void Interact_Internal(Transform player) { } /// 返回当前应播放的对话序列。子类根据任务状态返回不同版本。 protected virtual DialogueSequenceSO GetCurrentDialogue() => _defaultDialogue; // ── 对话播放 ─────────────────────────────────────────────────────── protected virtual void PlayDialogue(DialogueSequenceSO sequence, Transform player) { if (sequence == null) return; var manager = BaseGames.Core.ServiceLocator.GetOrDefault(); if (manager == null) { Debug.LogWarning($"[InteractableNPC:{_npcId}] DialogueManager 未注册到 ServiceLocator,无法播放对话。"); return; } manager.StartDialogue(sequence, _npcId); } } }