Files
zeling_v2/Assets/_Game/Scripts/UI/InputDeviceDetector.cs
Joywayer e879efaa89 Add InputDeviceIconSetSO configuration guide and related documentation
- Created a new markdown file detailing the configuration of InputDeviceIconSetSO.
- Included sections on system architecture, field explanations, image specifications, and complete workflow from setup to runtime.
- Documented the automatic device recognition logic and provided troubleshooting for common issues.
- Added references to relevant files and scripts for easier navigation.
2026-05-23 00:10:23 +08:00

110 lines
5.0 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.LowLevel;
namespace BaseGames.UI
{
/// <summary>
/// 设备检测器 —— 监听 InputSystem 的事件流,识别玩家最后使用的输入设备类型,
/// 并通过 InputDeviceTypeEventChannelSO 广播给全局。
///
/// 布置方式:挂在 UIRoot 或常驻 GameObject 上;只需存在一个实例。
/// </summary>
public sealed class InputDeviceDetector : MonoBehaviour
{
[Header("Event Channel")]
[Tooltip("广播当前设备类型变化")]
[SerializeField] private InputDeviceTypeEventChannelSO _onDeviceChanged;
/// <summary>当前活跃输入设备类型,供轮询使用。</summary>
public InputDeviceType CurrentDevice { get; private set; } = InputDeviceType.KeyboardMouse;
private void OnEnable()
{
// 监听所有输入事件:每次有任何 StateEvent/DeltaStateEvent 时触发
InputSystem.onEvent += OnInputSystemEvent;
// 监听设备连接/断开(热插拔)
InputSystem.onDeviceChange += OnDeviceChange;
}
private void OnDisable()
{
InputSystem.onEvent -= OnInputSystemEvent;
InputSystem.onDeviceChange -= OnDeviceChange;
}
// ── Event Handlers ────────────────────────────────────────────────────
private void OnInputSystemEvent(InputEventPtr eventPtr, InputDevice device)
{
// 只关心真实输入事件,滤掉内部状态事件
if (!eventPtr.IsA<StateEvent>() && !eventPtr.IsA<DeltaStateEvent>()) return;
var detected = ClassifyDevice(device);
if (detected == CurrentDevice) return;
CurrentDevice = detected;
_onDeviceChanged?.Raise(CurrentDevice);
}
private void OnDeviceChange(InputDevice device, InputDeviceChange change)
{
// 当设备重新连接时重新检测(防止手柄拔插后图标仍显示手柄图标)
if (change == InputDeviceChange.Reconnected || change == InputDeviceChange.Added)
{
// 保持当前 CurrentDevice 不变,等到实际输入事件再切换
}
}
// ── Device Classification ─────────────────────────────────────────────
/// <summary>
/// 根据 InputDevice 的布局层次识别设备类型。
/// Unity InputSystem 的设备层次:
/// DualShockGamepad → Gamepad → HID
/// XInputController → Gamepad → HID
/// SwitchProControllerHID → Gamepad → HID
/// Keyboard / Mouse
/// </summary>
private static InputDeviceType ClassifyDevice(InputDevice device)
{
if (device is Keyboard or Mouse)
return InputDeviceType.KeyboardMouse;
if (device is Gamepad gamepad)
{
var desc = gamepad.description;
string manufacturer = desc.manufacturer ?? string.Empty;
string product = desc.product ?? string.Empty;
string interfaceName = desc.interfaceName ?? string.Empty;
// PlayStation: DualShock 3/4 or DualSense (PS5)
if (InputSystem.IsFirstLayoutBasedOnSecond(gamepad.layout, "DualShockGamepad")
|| product.Contains("DualShock", System.StringComparison.OrdinalIgnoreCase)
|| product.Contains("DualSense", System.StringComparison.OrdinalIgnoreCase)
|| manufacturer.Contains("Sony", System.StringComparison.OrdinalIgnoreCase))
return InputDeviceType.PlayStationController;
// Nintendo Switch Pro Controller / Joy-Con
if (InputSystem.IsFirstLayoutBasedOnSecond(gamepad.layout, "SwitchProControllerHID")
|| product.Contains("Switch", System.StringComparison.OrdinalIgnoreCase)
|| product.Contains("Joy-Con", System.StringComparison.OrdinalIgnoreCase)
|| manufacturer.Contains("Nintendo", System.StringComparison.OrdinalIgnoreCase))
return InputDeviceType.SwitchController;
// Xbox / XInput (DirectInput 会走 HID 路径XInput 走 XInputController)
if (InputSystem.IsFirstLayoutBasedOnSecond(gamepad.layout, "XInputController")
|| product.Contains("Xbox", System.StringComparison.OrdinalIgnoreCase)
|| interfaceName.Equals("XInput", System.StringComparison.OrdinalIgnoreCase))
return InputDeviceType.XboxController;
// 未知手柄 → 默认 Xbox 图标集
return InputDeviceType.XboxController;
}
// 无法识别 → 键鼠
return InputDeviceType.KeyboardMouse;
}
}
}