摄像机区域的架构改动

This commit is contained in:
2026-05-15 14:47:24 +08:00
parent 1b37297585
commit f264329751
3591 changed files with 1687228 additions and 446503 deletions

View File

@@ -0,0 +1,88 @@
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();
// ── IInteractableOnInteract 模式)──────────────────────────────
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;
// 捕获局部变量,避免回调内通过 this 访问被销毁的对象
var cutsceneId = _cutscene.cutsceneId;
var worldState = _worldState;
_cutsceneManager.PlayCutscene(_cutscene, onCompleted: () =>
{
// 过场完全结束后才写入 flag确保异常中断时可重触
worldState?.SetFlag($"cutscene_played_{cutsceneId}");
});
// 区域触发后禁用自身,防止重入
if (_mode == TriggerMode.OnEnter) enabled = false;
}
}
}