using System; using UnityEngine; using System.Collections.Generic; namespace SK.Framework { public sealed class KeyInputController { private class KeyInputInfo { public readonly KeyCode keyCode; public readonly List keyInputs; public InputState state = InputState.None; public KeyInputInfo(KeyCode keyCode) { this.keyCode = keyCode; keyInputs = new List(); } public void Reset() { state = InputState.None; } } private readonly List keyInputs; private readonly List infos; private readonly Dictionary triggers; public KeyInputController() { keyInputs = new List(); infos = new List(); triggers = new Dictionary(); } public void Update() { for (int i = 0; i < keyInputs.Count; i++) { keyInputs[i].Value = Input.GetKey(keyInputs[i].Key); } for (int i = 0; i < infos.Count; i++) { var info = infos[i]; bool flag = false; for (int j = info.keyInputs.Count - 1; j >= 0; j--) { if (info.keyInputs[j].Value) { flag = true; break; } } if (flag) { info.state = info.state == InputState.None || info.state == InputState.Released ? InputState.Pressed : InputState.Held; triggers.Clear(); } else if (triggers.ContainsKey(info.keyCode)) { switch (triggers[info.keyCode].type) { case InputTriggerType.Pressed: info.state = InputState.Pressed; triggers.Remove(info.keyCode); break; case InputTriggerType.Held: info.state = InputState.Held; if (triggers[info.keyCode].disposeWhen.Invoke()) triggers.Remove(info.keyCode); break; case InputTriggerType.Released: info.state = InputState.Released; triggers.Remove(info.keyCode); break; } } else { info.state = info.state == InputState.Pressed || info.state == InputState.Held ? InputState.Released : InputState.None; } } } public void Reset() { for (int i = 0; i < keyInputs.Count; i++) { keyInputs[i].Reset(); } } public bool Register(KeyInput keyInput) { if (keyInputs.Contains(keyInput)) { return false; } keyInputs.Add(keyInput); var target = infos.Find(m => m.keyCode == keyInput.Key); if (target == null) { target = new KeyInputInfo(keyInput.Key); infos.Add(target); } target.keyInputs.Add(keyInput); return true; } public bool Unregister(KeyInput keyInput) { if (!keyInputs.Contains(keyInput)) { return false; } keyInputs.Remove(keyInput); var target = infos.Find(m => m.keyCode == keyInput.Key); if (target != null) { target.keyInputs.Remove(keyInput); if (target.keyInputs.Count == 0) { infos.Remove(target); } } return true; } public bool GetKeyDown(KeyInput keyInput) { var target = infos.Find(m => m.keyCode == keyInput.Key); return target != null && target.state == InputState.Pressed; } public bool GetKey(KeyInput keyInput) { var target = infos.Find(m => m.keyCode == keyInput.Key); return target != null && (target.state == InputState.Held || target.state == InputState.Pressed); } public bool GetKeyUp(KeyInput keyInput) { var target = infos.Find(m => m.keyCode == keyInput.Key); return target != null && target.state == InputState.Released; } public void Trigger(KeyCode keyCode, InputTriggerType type) { if (keyCode != KeyCode.None && !triggers.ContainsKey(keyCode) && type != InputTriggerType.Held) { triggers.Add(keyCode, new InputTrigger(type)); Debug.Log($"触发键盘按键 [{keyCode}] {(type == InputTriggerType.Pressed ? "按下" : "抬起")}"); } } public void Trigger(KeyCode keyCode, InputTriggerType type, Func disposeWhen) { if (keyCode != KeyCode.None && !triggers.ContainsKey(keyCode) && type == InputTriggerType.Held) { triggers.Add(keyCode, new InputTrigger(type, disposeWhen)); Debug.Log($"触发键盘按键 [{keyCode}] 持续按下"); } } } }