using System; using System.Collections; using System.Collections.Generic; using BaseGames.Core; using BaseGames.Core.Events; using UnityEngine; namespace BaseGames.EventChain { /// /// 世界事件链管理器(架构 14_NarrativeModule §10)。 /// 订阅游戏各系统的 SO 事件频道,转发为中继 C# 事件供 ChainCondition.Register() 绑定。 /// 每当收到新事件时,检查所有链的触发条件。 /// public class EventChainManager : MonoBehaviour { [Header("所有事件链")] [SerializeField] private EventChainSO[] _chains; [Header("事件频道(中继)")] [SerializeField] private StringEventChannelSO _onBossDefeated; // EVT_EnemyDied(bossId) [SerializeField] private StringEventChannelSO _onCollectiblePickedUp; // EVT_CollectiblePickup [SerializeField] private StringEventChannelSO _onAbilityUnlocked; // EVT_AbilityUnlocked [SerializeField] private StringEventChannelSO _onRoomEntered; // EVT_SceneLoaded [SerializeField] private StringEventChannelSO _onDialogueCompleted; // EVT_NpcDialogueCompleted // ── 中继 C# 事件,供 ChainCondition.Register() 订阅 ────────────── public event Action OnBossDefeated; public event Action OnCollectiblePickedUp; public event Action OnAbilityUnlocked; public event Action OnRoomEntered; public event Action OnDialogueCompleted; /// 链执行完成时广播 chainId(供 ChainCompletedCondition)。 public event Action OnChainCompleted; #if UNITY_EDITOR /// /// Editor 专用静态事件:链执行完成时向编辑器窗口推送日志。 /// 仅在编辑器构建中存在,不产生运行时开销。 /// EventChainEditorWindow 在 OnEnable 中订阅此事件。 /// public static event Action OnChainExecutedInEditor; #endif private readonly HashSet _completedChains = new(); private readonly CompositeDisposable _subs = new(); // ── 生命周期 ────────────────────────────────────────────────────── private void Awake() { // 从存档恢复已完成链 var sm = ServiceLocator.GetOrDefault(); if (sm != null) foreach (var id in sm.GetCompletedChains()) _completedChains.Add(id); } private void OnEnable() { _onBossDefeated?.Subscribe(id => { OnBossDefeated?.Invoke(id); EvaluateAll(); }).AddTo(_subs); _onCollectiblePickedUp?.Subscribe(id => { OnCollectiblePickedUp?.Invoke(id); EvaluateAll(); }).AddTo(_subs); _onAbilityUnlocked?.Subscribe(id => { OnAbilityUnlocked?.Invoke(id); EvaluateAll(); }).AddTo(_subs); _onRoomEntered?.Subscribe(id => { OnRoomEntered?.Invoke(id); EvaluateAll(); }).AddTo(_subs); _onDialogueCompleted?.Subscribe(id => { OnDialogueCompleted?.Invoke(id); EvaluateAll(); }).AddTo(_subs); // 向每个 Condition 注册中继事件 // 先重置 SO 资产上的运行时状态,防止跨 PlayMode 会话或多场景加载时状态残留 if (_chains == null) return; foreach (var chain in _chains) if (chain?.conditions != null) foreach (var cond in chain.conditions) { cond?.ResetState(); cond?.Register(this); } } private void OnDisable() { _subs.Clear(); if (_chains == null) return; foreach (var chain in _chains) if (chain?.conditions != null) foreach (var cond in chain.conditions) cond?.Unregister(this); } // ── 评估逻辑 ────────────────────────────────────────────────────── /// 收到新事件时立即评估所有链条件(无帧延迟)。 private void EvaluateAll() => DoEvaluateAll(); private void DoEvaluateAll() { if (_chains == null) return; foreach (var chain in _chains) { if (chain == null) continue; if (!chain.repeatable && _completedChains.Contains(chain.chainId)) continue; bool allMet = true; if (chain.conditions != null) foreach (var cond in chain.conditions) if (cond != null && !cond.IsMet()) { allMet = false; break; } if (allMet) StartCoroutine(ExecuteChain(chain)); } } private IEnumerator ExecuteChain(EventChainSO chain) { // 防重入:一次性链立即标记为已完成 if (!chain.repeatable) _completedChains.Add(chain.chainId); if (chain.actions != null) foreach (var action in chain.actions) { if (action == null) continue; yield return action.ExecuteAsync(this); if (chain.actionDelay > 0f) yield return new WaitForSeconds(chain.actionDelay); } ServiceLocator.GetOrDefault()?.SetChainCompleted(chain.chainId); OnChainCompleted?.Invoke(chain.chainId); #if UNITY_EDITOR OnChainExecutedInEditor?.Invoke(chain.chainId, "执行完成"); #endif } } }