引入InputSystem,输入设备管理系统迭代中

This commit is contained in:
ALIENJACK\alien 2025-03-13 17:38:12 +08:00
parent 3c10873180
commit 955a35659a
15 changed files with 372 additions and 60 deletions

View File

@ -10,7 +10,7 @@ GameObject:
m_Component:
- component: {fileID: 3186794564434009199}
- component: {fileID: 1464475178787633862}
- component: {fileID: 2053226018124086955}
- component: {fileID: 3126747713153700628}
m_Layer: 0
m_Name: EventSystem
m_TagString: Untagged
@ -48,7 +48,7 @@ MonoBehaviour:
m_FirstSelected: {fileID: 0}
m_sendNavigationEvents: 0
m_DragThreshold: 10
--- !u!114 &2053226018124086955
--- !u!114 &3126747713153700628
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
@ -57,17 +57,28 @@ MonoBehaviour:
m_GameObject: {fileID: 173080370084988713}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 4f231c4fb786f3946a6b90b886c48677, type: 3}
m_Script: {fileID: 11500000, guid: 01614664b831546d2ae94a42149d80ac, type: 3}
m_Name:
m_EditorClassIdentifier:
m_SendPointerHoverToParent: 1
m_HorizontalAxis: Horizontal
m_VerticalAxis: Vertical
m_SubmitButton: Submit
m_CancelButton: Cancel
m_InputActionsPerSecond: 10
m_RepeatDelay: 0.5
m_ForceModuleActive: 0
m_MoveRepeatDelay: 0.5
m_MoveRepeatRate: 0.1
m_XRTrackingOrigin: {fileID: 0}
m_ActionsAsset: {fileID: -944628639613478452, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3}
m_PointAction: {fileID: -1654692200621890270, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3}
m_MoveAction: {fileID: -8784545083839296357, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3}
m_SubmitAction: {fileID: 392368643174621059, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3}
m_CancelAction: {fileID: 7727032971491509709, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3}
m_LeftClickAction: {fileID: 3001919216989983466, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3}
m_MiddleClickAction: {fileID: -2185481485913320682, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3}
m_RightClickAction: {fileID: -4090225696740746782, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3}
m_ScrollWheelAction: {fileID: 6240969308177333660, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3}
m_TrackedDevicePositionAction: {fileID: 6564999863303420839, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3}
m_TrackedDeviceOrientationAction: {fileID: 7970375526676320489, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3}
m_DeselectOnBackgroundClick: 1
m_PointerBehavior: 0
m_CursorLockBehavior: 0
m_ScrollDeltaPerTick: 6
--- !u!1 &261166211120060501
GameObject:
m_ObjectHideFlags: 0

View File

@ -6,7 +6,8 @@
"VirtualNes.Core",
"UIEffect2018",
"Mame.Core",
"Essgee.Unity"
"Essgee.Unity",
"Unity.InputSystem"
],
"includePlatforms": [],
"excludePlatforms": [],

View File

@ -1,15 +1,30 @@
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;
namespace AxibugEmuOnline.Client.InputDevices
{
public class InputDevicesManager
{
InputResolver m_inputResolver = InputResolver.Create();
Dictionary<string, InputDevice> m_devices = new Dictionary<string, InputDevice>();
public InputDevicesManager()
{
AddDevice(new KeyBoard());
m_inputResolver.OnDeviceConnected += OnDeviceConnected;
m_inputResolver.OnDeviceLost += OnDeviceLost;
foreach (var device in m_inputResolver.GetDevices())
AddDevice(device);
}
private void OnDeviceLost(InputDevice lostDevice)
{
}
private void OnDeviceConnected(InputDevice connectDevice)
{
throw new System.NotImplementedException();
}
public void AddDevice(InputDevice device)
@ -77,9 +92,10 @@ namespace AxibugEmuOnline.Client.InputDevices
public bool AnyKeyDown { get; private set; }
protected Dictionary<string, KeyBase> m_keyMapper = new Dictionary<string, KeyBase>();
public InputDevice()
protected InputResolver m_resolver;
public InputDevice(InputResolver resolver)
{
m_resolver = resolver;
foreach (var key in DefineKeys())
{
m_keyMapper[key.KeyName] = key;

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 8fec275f55ad33a4fbe0ce724bc7274f
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,133 @@
using System;
using System.Collections;
using System.Collections.Generic;
namespace AxibugEmuOnline.Client.InputDevices
{
/// <summary>
/// 双向字典
/// </summary>
/// <typeparam name="TKey"></typeparam>
/// <typeparam name="TValue"></typeparam>
public class DualWayDictionary<TKey, TValue> : IDictionary<TKey, TValue>, IDictionary
where TKey : notnull
where TValue : notnull
{
private readonly Dictionary<TKey, TValue> _forward = new();
private readonly Dictionary<TValue, TKey> _reverse = new();
// 显式实现非泛型接口
bool IDictionary.IsFixedSize => false;
bool IDictionary.IsReadOnly => false;
bool ICollection.IsSynchronized => false;
object ICollection.SyncRoot => ((ICollection)_forward).SyncRoot;
// 泛型接口实现
public TValue this[TKey key]
{
get => _forward[key];
set
{
if (_forward.TryGetValue(key, out var oldValue))
_reverse.Remove(oldValue);
_forward[key] = value;
_reverse[value] = key;
}
}
object? IDictionary.this[object key]
{
get => key is TKey k ? _forward[k] : null;
set
{
if (key is TKey tk && value is TValue tv)
this[tk] = tv;
}
}
public ICollection<TKey> Keys => _forward.Keys;
public ICollection<TValue> Values => _forward.Values;
ICollection IDictionary.Keys => _forward.Keys;
ICollection IDictionary.Values => _forward.Values;
public int Count => _forward.Count;
public bool IsReadOnly => false;
// 双向查询扩展
public bool TryGetKey(TValue value, out TKey key) => _reverse.TryGetValue(value, out key);
public bool TryGetValue(TKey key, out TValue value) => _forward.TryGetValue(key, out value);
// 接口方法实现
public void Add(TKey key, TValue value)
{
if (_forward.ContainsKey(key) || _reverse.ContainsKey(value))
throw new ArgumentException("键或值已存在");
_forward.Add(key, value);
_reverse.Add(value, key);
}
public void Add(KeyValuePair<TKey, TValue> item) => Add(item.Key, item.Value);
void IDictionary.Add(object key, object value)
{
if (key is TKey k && value is TValue v)
Add(k, v);
else
throw new ArgumentException("类型不匹配");
}
public bool Contains(object key) => key is TKey k && _forward.ContainsKey(k);
public bool Contains(KeyValuePair<TKey, TValue> item) => _forward.TryGetValue(item.Key, out var v) && v.Equals(item.Value);
public bool ContainsKey(TKey key) => _forward.ContainsKey(key);
public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
{
((ICollection<KeyValuePair<TKey, TValue>>)_forward).CopyTo(array, arrayIndex);
}
public void CopyTo(Array array, int index)
{
((ICollection)_forward).CopyTo(array, index);
}
public bool Remove(TKey key)
{
if (!_forward.Remove(key, out var value)) return false;
_reverse.Remove(value);
return true;
}
public bool Remove(KeyValuePair<TKey, TValue> item) => Remove(item.Key);
void IDictionary.Remove(object key)
{
if (key is TKey k) Remove(k);
}
public void Clear()
{
_forward.Clear();
_reverse.Clear();
}
// 枚举器实现
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator() => _forward.GetEnumerator();
IDictionaryEnumerator IDictionary.GetEnumerator() => new DictionaryEnumerator(_forward.GetEnumerator());
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
// 非泛型枚举器适配器
private class DictionaryEnumerator : IDictionaryEnumerator
{
private readonly IEnumerator<KeyValuePair<TKey, TValue>> _enumerator;
public DictionaryEnumerator(IEnumerator<KeyValuePair<TKey, TValue>> enumerator) => _enumerator = enumerator;
public DictionaryEntry Entry => new(_enumerator.Current.Key, _enumerator.Current.Value);
public object Key => _enumerator.Current.Key;
public object? Value => _enumerator.Current.Value;
public object Current => Entry;
public bool MoveNext() => _enumerator.MoveNext();
public void Reset() => _enumerator.Reset();
}
}
}

View File

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: c1c60fee919bdf34983705af53c629f6

View File

@ -0,0 +1,57 @@
using System.Collections.Generic;
namespace AxibugEmuOnline.Client.InputDevices
{
public abstract class InputResolver
{
public static InputResolver Create()
{
#if ENABLE_INPUT_SYSTEM //InputSystem
return new InputSystemResolver();
#elif UNITY_PSP2 //SDK
throw new System.NotImplementedException();
#elif UNITY_PS3 //SDK
throw new System.NotImplementedException();
#else //使用旧Input
throw new System.NotImplementedException();
#endif
}
/// <summary> 禁止外部构造 </summary>
protected InputResolver()
{
OnInit();
}
protected abstract void OnInit();
/// <summary>
/// 获得所有当前已连入的输入设备
/// </summary>
/// <returns></returns>
public abstract IEnumerable<InputDevice> GetDevices();
/// <summary>
/// 检查指定输入设备是否还保持着连接
/// </summary>
/// <returns></returns>
public abstract bool CheckOnline(InputDevice device);
/// <param name="lostDevice">丢失的设备</param>
public delegate void OnDeviceLostHandle(InputDevice lostDevice);
/// <summary> 当设备丢失时触发 </summary>
public event OnDeviceLostHandle OnDeviceLost;
protected void RaiseDeviceLost(InputDevice lostDevice)
{
OnDeviceLost?.Invoke(lostDevice);
}
/// <param name="connectDevice">建立连接的设备</param>
public delegate void OnDeviceConnectedHandle(InputDevice connectDevice);
/// <summary> 当设备连接时触发 </summary>
public event OnDeviceConnectedHandle OnDeviceConnected;
protected void RaiseDeviceConnected(InputDevice connectDevice)
{
OnDeviceConnected?.Invoke(connectDevice);
}
}
}

View File

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 120c0ed2a5e098a4d84325be244aa9f3

View File

@ -0,0 +1,65 @@
#if ENABLE_INPUT_SYSTEM
using System.Collections.Generic;
using IP = UnityEngine.InputSystem.InputSystem;
using IPDevice = UnityEngine.InputSystem.InputDevice;
using IPKeyboard = UnityEngine.InputSystem.Keyboard;
namespace AxibugEmuOnline.Client.InputDevices
{
/// <summary> InputSystem对接 </summary>
public class InputSystemResolver : InputResolver
{
DualWayDictionary<IPDevice, InputDevice> m_devices = new DualWayDictionary<IPDevice, InputDevice>();
protected override void OnInit()
{
foreach (var device in IP.devices)
{
AddDevice(device);
}
IP.onDeviceChange += IP_onDeviceChange;
}
private void AddDevice(IPDevice ipdev)
{
InputDevice newDevice = null;
if (ipdev is IPKeyboard) newDevice = new KeyBoard(this);
if (newDevice != null)
{
m_devices.Add(ipdev, newDevice);
RaiseDeviceConnected(newDevice);
}
}
private void RemoveDevice(IPDevice ipdev)
{
if (m_devices.TryGetValue(ipdev, out var device))
{
m_devices.Remove(ipdev);
RaiseDeviceLost(device);
}
}
public override bool CheckOnline(InputDevice device)
{
return m_devices.TryGetKey(device, out var _);
}
private void IP_onDeviceChange(IPDevice device, UnityEngine.InputSystem.InputDeviceChange changeType)
{
switch (changeType)
{
case UnityEngine.InputSystem.InputDeviceChange.Added: AddDevice(device); break;
case UnityEngine.InputSystem.InputDeviceChange.Removed: RemoveDevice(device); break;
}
}
public override IEnumerable<InputDevice> GetDevices()
{
return m_devices.Values;
}
}
}
#endif

View File

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: e56617975c158684eb627cfb4a1c3ebd

View File

@ -1,13 +1,53 @@
using System;
using System.Collections.Generic;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
namespace AxibugEmuOnline.Client.InputDevices
{
public class KeyBoard : InputDevice
public partial class KeyBoard : InputDevice
{
public override string UniqueName => nameof(KeyBoard);
public override bool Online => true;
public KeyBoard(InputResolver resolver) : base(resolver) { }
protected override IEnumerable<KeyBase> DefineKeys()
{
var keys = s_keyboardKeys.Select(kc => new KeyboardKey(kc) as KeyBase);
return keys;
}
public class KeyboardKey : KeyBase
{
internal KeyCode m_listenKey;
public KeyboardKey(KeyCode listenKey)
{
m_listenKey = listenKey;
}
public override bool GetButtonDown()
{
return Input.GetKeyDown(m_listenKey);
}
public override bool GetButtonUp()
{
return Input.GetKeyUp(m_listenKey);
}
public override bool IsPressing()
{
return Input.GetKey(m_listenKey);
}
public override string KeyName => m_listenKey.ToString();
}
}
#region HardCodeForKeyboard
public partial class KeyBoard : InputDevice
{
#region HardCodeForKeyboard
static readonly List<KeyCode> s_keyboardKeys = new List<KeyCode>
{
// 字母键 A-Z
@ -50,6 +90,7 @@ namespace AxibugEmuOnline.Client.InputDevices
KeyCode.End, KeyCode.PageUp, KeyCode.PageDown, KeyCode.Pause, KeyCode.ScrollLock,
KeyCode.Clear
};
// 字母键 A-Z
public KeyboardKey A { get; private set; } = new KeyboardKey(KeyCode.A);
public KeyboardKey B { get; private set; } = new KeyboardKey(KeyCode.B);
@ -174,42 +215,6 @@ namespace AxibugEmuOnline.Client.InputDevices
public KeyboardKey Pause { get; private set; } = new KeyboardKey(KeyCode.Pause);
public KeyboardKey ScrollLock { get; private set; } = new KeyboardKey(KeyCode.ScrollLock);
public KeyboardKey Clear { get; private set; } = new KeyboardKey(KeyCode.Clear);
#endregion
public override string UniqueName => nameof(KeyBoard);
public override bool Online => true;
protected override IEnumerable<KeyBase> DefineKeys()
{
var keys = s_keyboardKeys.Select(kc => new KeyboardKey(kc) as KeyBase);
return keys;
}
public class KeyboardKey : KeyBase
{
internal KeyCode m_listenKey;
public KeyboardKey(KeyCode listenKey)
{
m_listenKey = listenKey;
}
public override bool GetButtonDown()
{
return Input.GetKeyDown(m_listenKey);
}
public override bool GetButtonUp()
{
return Input.GetKeyUp(m_listenKey);
}
public override bool IsPressing()
{
return Input.GetKey(m_listenKey);
}
public override string KeyName => m_listenKey.ToString();
}
}
#endregion
}

View File

@ -1,4 +1,4 @@
using System;
using System;
using System.Collections;
using UnityEngine;
using UnityEngine.UI;
@ -14,8 +14,6 @@ namespace AxibugEmuOnline.Client
public static bool IsInputing { get; private set; }
protected override void OnShow(object param)
{
ValueTuple<Action<string>, string, string> t = (ValueTuple<Action<string>, string, string>)param;
@ -30,7 +28,7 @@ namespace AxibugEmuOnline.Client
base.Update();
IsInputing = m_input.isFocused;
if (IsInputing && Input.GetButtonDown("Submit"))
{
OnCmdEnter();

View File

@ -2,6 +2,7 @@
"dependencies": {
"com.unity.2d.sprite": "1.0.0",
"com.unity.ide.visualstudio": "2.0.22",
"com.unity.inputsystem": "1.11.2",
"com.unity.test-framework": "1.4.5",
"com.unity.ugui": "2.0.0",
"com.unity.modules.accessibility": "1.0.0",

View File

@ -22,6 +22,15 @@
},
"url": "https://packages.unity.com"
},
"com.unity.inputsystem": {
"version": "1.11.2",
"depth": 0,
"source": "registry",
"dependencies": {
"com.unity.modules.uielements": "1.0.0"
},
"url": "https://packages.unity.com"
},
"com.unity.test-framework": {
"version": "1.4.5",
"depth": 0,

View File

@ -8,4 +8,6 @@ EditorBuildSettings:
- enabled: 1
path: Assets/Scene/AxibugEmuOnline.Client.unity
guid: eb0c18a619175384d95147898a43054b
m_configObjects: {}
m_configObjects:
com.unity.input.settings.actions: {fileID: -944628639613478452, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3}
m_UseUCBPForAssetBundles: 0