using UnityEngine; using BaseGames.Core.Events; namespace BaseGames.Input { /// /// 运行时初始化 InputReaderSO,并让输入 ActionMap 跟随游戏状态切换。 /// 挂在 Persistent 场景的 InputReaderHolder 上。 /// /// 输入模式由游戏状态驱动(通过 EVT_GameStateChanged 频道订阅,避免 Core→Input 程序集循环): /// · Gameplay / BossFight → 启用 Gameplay 输入 /// · 其余状态(MainMenu / Paused / Dead / Cutscene / LoadingScene / Initializing 等)→ 启用 UI 输入 /// /// 这样主菜单等 UI 场景下 UI ActionMap 才会被启用,保证 EventSystem(InputSystemUIInputModule) /// 能接收鼠标点击 / 手柄导航。Dialogue / Cutscene 等 Gameplay 内子流程的临时切换由各自管理器处理, /// 不经过此处(其状态仍为 Gameplay,本组件不干预)。 /// /// _inputReader 与 _onGameStateChanged 必须在 Inspector 中赋值,框架不提供运行时自动查找回退。 /// public sealed class InputReaderBootstrap : MonoBehaviour { [SerializeField] private InputReaderSO _inputReader; [Header("状态驱动输入切换")] [Tooltip("游戏状态变化频道(EVT_GameStateChanged)。据此在 Gameplay 输入与 UI 输入间切换。")] [SerializeField] private GameStateEventChannelSO _onGameStateChanged; private readonly CompositeDisposable _subs = new(); private void Awake() { Debug.Assert(_inputReader != null, "[InputReaderBootstrap] _inputReader 未在 Inspector 中赋值!请在 Persistent 场景的 InputReaderHolder 上手动指定 InputReaderSO 资产。", this); Debug.Assert(_onGameStateChanged != null, "[InputReaderBootstrap] _onGameStateChanged 未赋值,请在 Inspector 中指定 EVT_GameStateChanged,否则输入模式无法跟随游戏状态切换。", this); } private void OnEnable() { _onGameStateChanged?.Subscribe(HandleGameStateChanged).AddTo(_subs); } private void Start() { if (_inputReader == null) return; _inputReader.LoadBindingOverrides(); // 从 PlayerPrefs 恢复用户自定义绑定 // 启动初始状态为 Initializing → MainMenu,使用 UI 输入作为兜底; // 之后由 HandleGameStateChanged 跟随游戏状态切换(不再硬编码 EnableGameplayInput)。 _inputReader.EnableUIInput(); } private void HandleGameStateChanged(GameStateId state) { if (_inputReader == null) return; // Gameplay / BossFight 使用游戏输入;其余状态(菜单 / 暂停 / 死亡 / 过场 / 加载)使用 UI 输入。 bool gameplay = state.Id == "Gameplay" || state.Id == "BossFight"; if (gameplay) _inputReader.EnableGameplayInput(); else _inputReader.EnableUIInput(); } private void OnDisable() { _subs.Clear(); _inputReader?.DisableAllInput(); } } }