using BaseGames.Core.Events; using UnityEngine; using UnityEngine.Playables; using UnityEngine.Timeline; namespace BaseGames.Cutscene { // ===================================================================== // SignalEmitterClip —— Timeline 零耦合事件桥接(架构 14 §11.6) // ===================================================================== /// /// 在 Timeline 轨道上放置此 Clip,Clip 播放时向目标 Void 事件频道 Raise 一次事件。 /// 用途:Timeline 动画与游戏逻辑保持零耦合(不直接引用场景对象)。 /// 使用场景示例:过场第 3 秒 → 触发 EVT_BossPhase2 → BossOrchestrator 切换阶段。 /// [CreateAssetMenu(menuName = "BaseGames/Cutscene/SignalEmitterClip")] public class SignalEmitterClip : PlayableAsset, ITimelineClipAsset { [Tooltip("Clip 播放时发射的目标 Void 事件频道 SO")] [SerializeField] private VoidEventChannelSO _targetChannel; /// Timeline 系统查询 Clip 能力(无额外能力)。 public ClipCaps clipCaps => ClipCaps.None; public override Playable CreatePlayable(PlayableGraph graph, GameObject owner) { var playable = ScriptPlayable.Create(graph); playable.GetBehaviour().Clip = this; return playable; } /// 供 SignalEmitterBehaviour 内部调用,发射事件。 internal void Fire() => _targetChannel?.Raise(); } // ───────────────────────────────────────────────────────────────────── /// /// SignalEmitterClip 对应的 PlayableBehaviour,处理 ProcessFrame 时机。 /// public class SignalEmitterBehaviour : PlayableBehaviour { /// 由 CreatePlayable 注入,内部访问 Fire() 发射事件。 public SignalEmitterClip Clip; private bool _fired; public override void OnBehaviourPlay(Playable playable, FrameData info) { _fired = false; // 支持 Timeline 循环/重播时重置 } public override void ProcessFrame(Playable playable, FrameData info, object playerData) { if (!_fired && Clip != null) { Clip.Fire(); _fired = true; } } } }