using UnityEngine; using UnityEngine.InputSystem; namespace Agame { /// /// 输入资产 Assets/_Game/Input/PlayerControls.inputactions 的名称与取值入口。 /// /// 把 Action 名集中在这里,是为了避免 "Move"/"Look"/"Attack" 这类字符串散落在三个脚本里 —— /// 将来在输入资产里改名,只需要动这一处。 /// /// 约定:三个玩家脚本一律从 PlayerInput 实例上取 Action,而不是各自序列化一个资产引用。 /// 因为 PlayerInput 可能为每个玩家实例化一份 Actions 副本,从实例上取才能拿到正确的那一份。 /// public static class PlayerInputNames { /// 输入资产的文件名,仅用于错误提示。 public const string AssetFileName = "PlayerControls.inputactions"; /// Action Map 名称,需与输入资产中的 Map 一致。 public const string ActionMap = "Player"; public const string Move = "Move"; public const string Look = "Look"; public const string Jump = "Jump"; public const string Sprint = "Sprint"; public const string Attack = "Attack"; /// /// 从 PlayerInput 上解析指定 Action,解析失败时返回 null 并给出明确的错误信息。 /// 这里刻意用 LogError 而不是直接抛 NullReferenceException —— /// "输入没反应但又不报错"是这类问题里最难排查的一种,必须留下痕迹。 /// public static InputAction Resolve(PlayerInput playerInput, string actionName, Object context) { string ownerName = context != null ? context.name : "(未知对象)"; if (playerInput == null) { Debug.LogError( $"[{nameof(PlayerInputNames)}] {ownerName} 上找不到 PlayerInput 组件,无法读取输入。" + $"请在玩家预制体上加 PlayerInput 组件,并把 Actions 指向 {AssetFileName}。", context); return null; } InputActionAsset asset = playerInput.actions; if (asset == null) { Debug.LogError( $"[{nameof(PlayerInputNames)}] {ownerName} 的 PlayerInput 没有指定 Actions 资产," + $"请把 {AssetFileName} 拖进 PlayerInput 的 Actions 槽。", context); return null; } InputAction action = asset.FindAction(actionName, throwIfNotFound: false); if (action == null) { Debug.LogError( $"[{nameof(PlayerInputNames)}] {AssetFileName} 里找不到名为 \"{actionName}\" 的动作," + "请确认 Map 与 Action 名和脚本里的一致。", context); return null; } return action; } } }