地图系统

This commit is contained in:
2026-06-05 18:41:33 +08:00
parent 613f2a4d13
commit fe4fd60083
234 changed files with 33090 additions and 4899 deletions

View File

@@ -1,32 +1,68 @@
using UnityEngine;
using BaseGames.Core.Events;
namespace BaseGames.Input
{
/// <summary>
/// 运行时启用 InputReaderSO ActionMap。
/// 运行时初始化 InputReaderSO,并让输入 ActionMap 跟随游戏状态切换
/// 挂在 Persistent 场景的 InputReaderHolder 上。
/// _inputReader 必须在 Inspector 中赋值,框架不提供运行时自动查找回退。
///
/// 输入模式由游戏状态驱动(通过 EVT_GameStateChanged 频道订阅,避免 Core→Input 程序集循环):
/// · Gameplay / BossFight → 启用 Gameplay 输入
/// · 其余状态MainMenu / Paused / Dead / Cutscene / LoadingScene / Initializing 等)→ 启用 UI 输入
///
/// 这样主菜单等 UI 场景下 UI ActionMap 才会被启用,保证 EventSystemInputSystemUIInputModule
/// 能接收鼠标点击 / 手柄导航。Dialogue / Cutscene 等 Gameplay 内子流程的临时切换由各自管理器处理,
/// 不经过此处(其状态仍为 Gameplay本组件不干预
///
/// _inputReader 与 _onGameStateChanged 必须在 Inspector 中赋值,框架不提供运行时自动查找回退。
/// </summary>
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 恢复用户自定义绑定
_inputReader.EnableGameplayInput();
// 启动初始状态为 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();
}
}

View File

@@ -12,6 +12,18 @@ namespace BaseGames.Input
[SerializeField] private InputActionAsset _inputActions;
[SerializeField] private VoidEventChannelSO _onPauseRequested;
[Header("背包菜单InventoryHub")]
[Tooltip("打开统一背包菜单。对应 EVT_InventoryOpen。绑定到 UI/Gameplay Map 的 \"Inventory\" Action可选。")]
[SerializeField] private VoidEventChannelSO _onInventoryOpen;
[Tooltip("背包 Tab下一页L/R 肩键)。对应 EVT_InventoryTabNext。绑定 \"InventoryTabNext\" Action可选。")]
[SerializeField] private VoidEventChannelSO _onInventoryTabNext;
[Tooltip("背包 Tab上一页L/R 肩键)。对应 EVT_InventoryTabPrev。绑定 \"InventoryTabPrev\" Action可选。")]
[SerializeField] private VoidEventChannelSO _onInventoryTabPrev;
[Header("UI 操作")]
[Tooltip("UI 取消操作ESC / 手柄 B·Circle。由 UIManager 全局订阅,关闭当前栈顶面板。对应 EVT_UICancelPressed。")]
[SerializeField] private VoidEventChannelSO _onUICancelPressed;
// ── Gameplay Events ───────────────────────────────────────────────────
public event Action<Vector2> MoveEvent;
public event Action JumpStartedEvent;
@@ -194,19 +206,24 @@ namespace BaseGames.Input
BindStarted(_gameplay, "Pause", HandlePause);
// 背包菜单开关(可选 Action默认绑定如 I 键 / 手柄 Select。未在 Map 中定义则跳过。
BindStarted(_gameplay, "Inventory", () => _onInventoryOpen?.Raise());
if (_ui != null)
{
BindPerformed(_ui, "Navigate", ctx => NavigateEvent?.Invoke(ctx.ReadValue<Vector2>()));
BindCanceled(_ui, "Navigate", _ => NavigateEvent?.Invoke(Vector2.zero));
BindStarted(_ui, "Submit", () => SubmitEvent?.Invoke());
BindStarted(_ui, "Cancel", () => CancelEvent?.Invoke());
BindStarted(_ui, "Cancel", () => { CancelEvent?.Invoke(); _onUICancelPressed?.Raise(); });
BindStarted(_ui, "Pause", HandlePause);
BindPerformed(_ui, "Point", ctx => PointEvent?.Invoke(ctx.ReadValue<Vector2>()));
// R13-N3 小地图缩放档位切换Action 名称需在 InputActionAsset UI Map 中添加(可选)
BindStarted(_ui, "CycleMinimapZoom", () => CycleMinimapZoomEvent?.Invoke());
// R13-N4 全屏地图居中Action 名称需在 InputActionAsset UI Map 中添加(可选)
BindStarted(_ui, "MapCenter", () => MapCenterEvent?.Invoke());
// 背包 Tab 循环L/R 肩键Action 名称需在 InputActionAsset UI Map 中添加(可选)
BindStarted(_ui, "InventoryTabNext", () => _onInventoryTabNext?.Raise());
BindStarted(_ui, "InventoryTabPrev", () => _onInventoryTabPrev?.Raise());
}
_isBound = true;