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