update InputReader
This commit is contained in:
parent
88af70ff61
commit
a63324959a
@ -3,14 +3,26 @@ using System.Collections.Generic;
|
|||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.InputSystem;
|
using UnityEngine.InputSystem;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 输入读取工具。
|
||||||
|
/// 负责运行时输入轮询、单次触发和切换态管理,
|
||||||
|
/// 与 InputBindingManager 的绑定/重绑定职责分离。
|
||||||
|
/// </summary>
|
||||||
public static class InputActionReader
|
public static class InputActionReader
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 用于标识一次输入读取上下文。
|
||||||
|
/// 同一个 Action 在不同 owner 或 key 下会拥有独立的按下状态。
|
||||||
|
/// </summary>
|
||||||
private readonly struct InputReadKey : IEquatable<InputReadKey>
|
private readonly struct InputReadKey : IEquatable<InputReadKey>
|
||||||
{
|
{
|
||||||
public readonly string ActionName;
|
public readonly string ActionName;
|
||||||
public readonly int OwnerId;
|
public readonly int OwnerId;
|
||||||
public readonly string OwnerKey;
|
public readonly string OwnerKey;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 使用实例 ID 作为拥有者标识,适合 Unity 对象。
|
||||||
|
/// </summary>
|
||||||
public InputReadKey(string actionName, int ownerId)
|
public InputReadKey(string actionName, int ownerId)
|
||||||
{
|
{
|
||||||
ActionName = actionName ?? string.Empty;
|
ActionName = actionName ?? string.Empty;
|
||||||
@ -18,6 +30,9 @@ public static class InputActionReader
|
|||||||
OwnerKey = string.Empty;
|
OwnerKey = string.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 使用字符串作为拥有者标识,适合外部系统或手动传入的 key。
|
||||||
|
/// </summary>
|
||||||
public InputReadKey(string actionName, string ownerKey)
|
public InputReadKey(string actionName, string ownerKey)
|
||||||
{
|
{
|
||||||
ActionName = actionName ?? string.Empty;
|
ActionName = actionName ?? string.Empty;
|
||||||
@ -50,19 +65,30 @@ public static class InputActionReader
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 记录“本次按下已消费”的键,用于 Once 语义。
|
||||||
private static readonly HashSet<InputReadKey> PressedKeys = new();
|
private static readonly HashSet<InputReadKey> PressedKeys = new();
|
||||||
|
// 记录当前处于开启状态的切换键。
|
||||||
private static readonly HashSet<InputReadKey> ToggledKeys = new();
|
private static readonly HashSet<InputReadKey> ToggledKeys = new();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 直接读取指定 Action 的值。
|
||||||
|
/// </summary>
|
||||||
public static T ReadValue<T>(string actionName) where T : struct
|
public static T ReadValue<T>(string actionName) where T : struct
|
||||||
{
|
{
|
||||||
return ResolveAction(actionName).ReadValue<T>();
|
return ResolveAction(actionName).ReadValue<T>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 以 object 形式读取指定 Action 的值。
|
||||||
|
/// </summary>
|
||||||
public static object ReadValue(string actionName)
|
public static object ReadValue(string actionName)
|
||||||
{
|
{
|
||||||
return ResolveAction(actionName).ReadValueAsObject();
|
return ResolveAction(actionName).ReadValueAsObject();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 仅在 Action 处于按下状态时读取值。
|
||||||
|
/// </summary>
|
||||||
public static bool TryReadValue<T>(string actionName, out T value) where T : struct
|
public static bool TryReadValue<T>(string actionName, out T value) where T : struct
|
||||||
{
|
{
|
||||||
InputAction inputAction = ResolveAction(actionName);
|
InputAction inputAction = ResolveAction(actionName);
|
||||||
@ -76,6 +102,9 @@ public static class InputActionReader
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 仅在 Action 处于按下状态时以 object 形式读取值。
|
||||||
|
/// </summary>
|
||||||
public static bool TryReadValue(string actionName, out object value)
|
public static bool TryReadValue(string actionName, out object value)
|
||||||
{
|
{
|
||||||
InputAction inputAction = ResolveAction(actionName);
|
InputAction inputAction = ResolveAction(actionName);
|
||||||
@ -89,6 +118,10 @@ public static class InputActionReader
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 只在本次按下的第一帧返回 true,并输出当前值。
|
||||||
|
/// owner 用来隔离不同对象的读取状态。
|
||||||
|
/// </summary>
|
||||||
public static bool TryReadValueOnce<T>(UnityEngine.Object owner, string actionName, out T value) where T : struct
|
public static bool TryReadValueOnce<T>(UnityEngine.Object owner, string actionName, out T value) where T : struct
|
||||||
{
|
{
|
||||||
if (owner == null)
|
if (owner == null)
|
||||||
@ -100,6 +133,10 @@ public static class InputActionReader
|
|||||||
return TryReadValueOnceInternal(new InputReadKey(actionName, owner.GetInstanceID()), actionName, out value);
|
return TryReadValueOnceInternal(new InputReadKey(actionName, owner.GetInstanceID()), actionName, out value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 读取按钮型 Action。
|
||||||
|
/// 非按钮类型会直接抛出异常,避免误用。
|
||||||
|
/// </summary>
|
||||||
public static bool ReadButton(string actionName)
|
public static bool ReadButton(string actionName)
|
||||||
{
|
{
|
||||||
InputAction inputAction = ResolveAction(actionName);
|
InputAction inputAction = ResolveAction(actionName);
|
||||||
@ -111,41 +148,66 @@ public static class InputActionReader
|
|||||||
throw new NotSupportedException("[InputActionReader] The Input Action must be a button type.");
|
throw new NotSupportedException("[InputActionReader] The Input Action must be a button type.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 对 Unity 对象做一次性按钮读取。
|
||||||
|
/// </summary>
|
||||||
public static bool ReadButtonOnce(UnityEngine.Object owner, string actionName)
|
public static bool ReadButtonOnce(UnityEngine.Object owner, string actionName)
|
||||||
{
|
{
|
||||||
return owner != null && ReadButtonOnce(owner.GetInstanceID(), actionName);
|
return owner != null && ReadButtonOnce(owner.GetInstanceID(), actionName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 对实例 ID 做一次性按钮读取。
|
||||||
|
/// </summary>
|
||||||
public static bool ReadButtonOnce(int instanceID, string actionName)
|
public static bool ReadButtonOnce(int instanceID, string actionName)
|
||||||
{
|
{
|
||||||
return ReadButtonOnceInternal(new InputReadKey(actionName, instanceID), actionName);
|
return ReadButtonOnceInternal(new InputReadKey(actionName, instanceID), actionName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 对字符串 key 做一次性按钮读取。
|
||||||
|
/// </summary>
|
||||||
public static bool ReadButtonOnce(string key, string actionName)
|
public static bool ReadButtonOnce(string key, string actionName)
|
||||||
{
|
{
|
||||||
return ReadButtonOnceInternal(new InputReadKey(actionName, key), actionName);
|
return ReadButtonOnceInternal(new InputReadKey(actionName, key), actionName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 对 Unity 对象读取按钮切换态。
|
||||||
|
/// 每次新的按下沿会在开/关之间切换。
|
||||||
|
/// </summary>
|
||||||
public static bool ReadButtonToggle(UnityEngine.Object owner, string actionName)
|
public static bool ReadButtonToggle(UnityEngine.Object owner, string actionName)
|
||||||
{
|
{
|
||||||
return owner != null && ReadButtonToggle(owner.GetInstanceID(), actionName);
|
return owner != null && ReadButtonToggle(owner.GetInstanceID(), actionName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 对实例 ID 读取按钮切换态。
|
||||||
|
/// </summary>
|
||||||
public static bool ReadButtonToggle(int instanceID, string actionName)
|
public static bool ReadButtonToggle(int instanceID, string actionName)
|
||||||
{
|
{
|
||||||
return ReadButtonToggleInternal(new InputReadKey(actionName, instanceID), actionName);
|
return ReadButtonToggleInternal(new InputReadKey(actionName, instanceID), actionName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 对字符串 key 读取按钮切换态。
|
||||||
|
/// </summary>
|
||||||
public static bool ReadButtonToggle(string key, string actionName)
|
public static bool ReadButtonToggle(string key, string actionName)
|
||||||
{
|
{
|
||||||
return ReadButtonToggleInternal(new InputReadKey(actionName, key), actionName);
|
return ReadButtonToggleInternal(new InputReadKey(actionName, key), actionName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 重置指定 key 的切换态。
|
||||||
|
/// </summary>
|
||||||
public static void ResetToggledButton(string key, string actionName)
|
public static void ResetToggledButton(string key, string actionName)
|
||||||
{
|
{
|
||||||
ToggledKeys.Remove(new InputReadKey(actionName, key));
|
ToggledKeys.Remove(new InputReadKey(actionName, key));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 重置某个 Action 名称下的所有切换态。
|
||||||
|
/// </summary>
|
||||||
public static void ResetToggledButton(string actionName)
|
public static void ResetToggledButton(string actionName)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(actionName) || ToggledKeys.Count == 0)
|
if (string.IsNullOrEmpty(actionName) || ToggledKeys.Count == 0)
|
||||||
@ -164,17 +226,27 @@ public static class InputActionReader
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 清空全部切换态缓存。
|
||||||
|
/// </summary>
|
||||||
public static void ResetToggledButtons()
|
public static void ResetToggledButtons()
|
||||||
{
|
{
|
||||||
ToggledKeys.Clear();
|
ToggledKeys.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 解析 Action;找不到时立即抛错,避免静默失败。
|
||||||
|
/// </summary>
|
||||||
private static InputAction ResolveAction(string actionName)
|
private static InputAction ResolveAction(string actionName)
|
||||||
{
|
{
|
||||||
return InputBindingManager.Action(actionName)
|
return InputBindingManager.Action(actionName)
|
||||||
?? throw new InvalidOperationException($"[InputActionReader] Action '{actionName}' is not available.");
|
?? throw new InvalidOperationException($"[InputActionReader] Action '{actionName}' is not available.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 内部的单次值读取逻辑。
|
||||||
|
/// 当按键抬起时,会清理 PressedKeys 中对应状态。
|
||||||
|
/// </summary>
|
||||||
private static bool TryReadValueOnceInternal<T>(InputReadKey readKey, string actionName, out T value) where T : struct
|
private static bool TryReadValueOnceInternal<T>(InputReadKey readKey, string actionName, out T value) where T : struct
|
||||||
{
|
{
|
||||||
InputAction inputAction = ResolveAction(actionName);
|
InputAction inputAction = ResolveAction(actionName);
|
||||||
@ -195,6 +267,10 @@ public static class InputActionReader
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 内部的按钮单次触发逻辑。
|
||||||
|
/// 只有第一次按下返回 true,持续按住不会重复触发。
|
||||||
|
/// </summary>
|
||||||
private static bool ReadButtonOnceInternal(InputReadKey readKey, string actionName)
|
private static bool ReadButtonOnceInternal(InputReadKey readKey, string actionName)
|
||||||
{
|
{
|
||||||
if (ReadButton(actionName))
|
if (ReadButton(actionName))
|
||||||
@ -206,6 +282,10 @@ public static class InputActionReader
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 内部的按钮切换逻辑。
|
||||||
|
/// 基于 Once 触发,在每次新的按下沿时切换状态。
|
||||||
|
/// </summary>
|
||||||
private static bool ReadButtonToggleInternal(InputReadKey readKey, string actionName)
|
private static bool ReadButtonToggleInternal(InputReadKey readKey, string actionName)
|
||||||
{
|
{
|
||||||
if (ReadButtonOnceInternal(readKey, actionName))
|
if (ReadButtonOnceInternal(readKey, actionName))
|
||||||
|
|||||||
@ -19,7 +19,7 @@ public class InputBindingManager : MonoSingleton<InputBindingManager>
|
|||||||
[Tooltip("InputActionAsset to manage")]
|
[Tooltip("InputActionAsset to manage")]
|
||||||
public InputActionAsset actions;
|
public InputActionAsset actions;
|
||||||
|
|
||||||
public string fileName = "input_bindings.json";
|
private const string FILE_NAME = "input_bindings.json";
|
||||||
public bool debugMode = false;
|
public bool debugMode = false;
|
||||||
|
|
||||||
internal InputActionRebindingExtensions.RebindingOperation rebindOperation;
|
internal InputActionRebindingExtensions.RebindingOperation rebindOperation;
|
||||||
@ -71,7 +71,7 @@ public class InputBindingManager : MonoSingleton<InputBindingManager>
|
|||||||
#else
|
#else
|
||||||
string folder = Application.persistentDataPath;
|
string folder = Application.persistentDataPath;
|
||||||
#endif
|
#endif
|
||||||
cachedSavePath = Path.Combine(folder, fileName);
|
cachedSavePath = Path.Combine(folder, FILE_NAME);
|
||||||
return cachedSavePath;
|
return cachedSavePath;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user