82 lines
3.2 KiB
C#
82 lines
3.2 KiB
C#
using BaseGames.Core.Events;
|
||
using BaseGames.World;
|
||
using UnityEngine;
|
||
|
||
namespace BaseGames.Cutscene
|
||
{
|
||
/// <summary>
|
||
/// 过场动画触发器(架构 14_NarrativeModule §11.5)。
|
||
/// 支持四种触发模式:进入区域、玩家交互、场景加载、事件频道。
|
||
/// 实现 IInteractable 以支持 OnInteract 模式。
|
||
/// </summary>
|
||
public class CutsceneTrigger : MonoBehaviour, IInteractable
|
||
{
|
||
public enum TriggerMode
|
||
{
|
||
OnEnter, // 进入 Trigger 碰撞区域
|
||
OnInteract, // 玩家主动交互(IInteractable)
|
||
OnSceneLoad, // 场景加载完毕(Start)
|
||
OnEvent, // 订阅事件频道触发
|
||
}
|
||
|
||
[SerializeField] private CutsceneSO _cutscene;
|
||
[SerializeField] private TriggerMode _mode = TriggerMode.OnEnter;
|
||
[SerializeField] private CutsceneManager _cutsceneManager;
|
||
[SerializeField] private VoidEventChannelSO _triggerEventChannel; // OnEvent 模式使用
|
||
[SerializeField] private WorldStateRegistry _worldState; // SO 注入,记录/查询播放状态
|
||
|
||
private readonly CompositeDisposable _subs = new();
|
||
|
||
// ── IInteractable(OnInteract 模式)──────────────────────────────
|
||
public bool CanInteract => _mode == TriggerMode.OnInteract;
|
||
public string InteractPrompt => "查看";
|
||
|
||
public void Interact(Transform player) => TriggerCutscene();
|
||
public void OnPlayerEnterRange(Transform player) { }
|
||
public void OnPlayerExitRange() { }
|
||
|
||
// ── 生命周期 ──────────────────────────────────────────────────────
|
||
|
||
private void OnEnable()
|
||
{
|
||
if (_mode == TriggerMode.OnEvent)
|
||
_triggerEventChannel?.Subscribe(TriggerCutscene).AddTo(_subs);
|
||
}
|
||
|
||
private void OnDisable()
|
||
{
|
||
_subs.Clear();
|
||
}
|
||
|
||
private void Start()
|
||
{
|
||
if (_mode == TriggerMode.OnSceneLoad) TriggerCutscene();
|
||
}
|
||
|
||
private void OnTriggerEnter2D(Collider2D other)
|
||
{
|
||
if (_mode != TriggerMode.OnEnter) return;
|
||
if (!other.CompareTag("Player")) return;
|
||
TriggerCutscene();
|
||
}
|
||
|
||
// ── 触发逻辑 ──────────────────────────────────────────────────────
|
||
|
||
private void TriggerCutscene()
|
||
{
|
||
if (_cutscene == null || _cutsceneManager == null) return;
|
||
|
||
// 已播放且仅播一次 → 跳过
|
||
if (_cutscene.playOnlyOnce && _worldState != null
|
||
&& _worldState.HasFlag($"cutscene_played_{_cutscene.cutsceneId}"))
|
||
return;
|
||
|
||
_cutsceneManager.PlayCutscene(_cutscene);
|
||
_worldState?.SetFlag($"cutscene_played_{_cutscene.cutsceneId}");
|
||
|
||
// 区域触发后禁用自身,防止重入
|
||
if (_mode == TriggerMode.OnEnter) enabled = false;
|
||
}
|
||
}
|
||
}
|