using UnityEngine; using System.Collections.Generic; public class KeyBindingManager : MonoBehaviour { private static Dictionary keyBindings = new Dictionary(); private static readonly string[] colors = { "red", "green", "yellow", "purple", "blue" }; private static readonly KeyCode[] defaultKeys = { KeyCode.D, KeyCode.F, KeyCode.Space, KeyCode.J, KeyCode.K }; private const string SecondaryTrack3PrefsKey = "KeyBinding_yellow_secondary"; private static KeyCode secondaryTrack3Key = KeyCode.V; private static bool initialized = false; // Migration marker: once we've converted legacy (int)KeyCode prefs to the new // Input System path storage, we set this so we don't re-migrate. Storage stays // keyed by KeyCode for backward compatibility; paths are derived on demand from KeyCode. private const string BindingFormatVersionKey = "KeyBindingFormatVersion"; private const int BindingFormatVersion = 2; private void Awake() { if (!initialized) { LoadKeyBindings(); } Debug.Log("KeyBindingManager Awake() 被调用,开始加载按键映射..."); } // ---- Input System path accessors (new) ---- // The binding store remains KeyCode-based for backward compatibility with saved prefs. // These helpers translate the stored KeyCode into an Input System control path // (e.g. KeyCode.D -> "/d") for GameplayInputActions to bind at runtime. public static string GetBindingPathForTrack(int trackIndex) { if (trackIndex < 0 || trackIndex >= colors.Length) return null; return InputSystemKeyMap.KeyCodeToPath(GetKeyForColor(colors[trackIndex])); } public static string GetSecondaryTrack3BindingPath() { return InputSystemKeyMap.KeyCodeToPath(GetSecondaryKeyForTrack3()); } public static KeyCode GetKeyForColor(string color) { if (!initialized) { LoadKeyBindings(); } if (string.IsNullOrEmpty(color)) return KeyCode.None; var keyLower = color.ToLower(); if (keyBindings.TryGetValue(keyLower, out KeyCode key)) { return key; } // fallback: try to map by index order for (int i = 0; i < colors.Length; i++) { if (colors[i] == keyLower) { return defaultKeys[i]; } } return KeyCode.None; } public static KeyCode GetSecondaryKeyForTrack3() { if (!initialized) { LoadKeyBindings(); } return secondaryTrack3Key; } public static bool IsKeyForColor(string color, KeyCode key) { if (!initialized) { LoadKeyBindings(); } if (key == KeyCode.None || string.IsNullOrEmpty(color)) return false; string keyLower = color.ToLower(); if (GetKeyForColor(keyLower) == key) return true; return keyLower == "yellow" && secondaryTrack3Key == key; } public static void ChangeKeyBinding(string color, KeyCode newKey) { if (string.IsNullOrEmpty(color)) return; var keyLower = color.ToLower(); keyBindings[keyLower] = newKey; SaveKeyBindings(); } public static void ChangeSecondaryTrack3KeyBinding(KeyCode newKey) { secondaryTrack3Key = newKey; SaveKeyBindings(); } private static void SaveKeyBindings() { for (int i = 0; i < colors.Length; i++) { var col = colors[i]; KeyCode k = defaultKeys[i]; if (keyBindings.TryGetValue(col, out KeyCode stored)) k = stored; PlayerPrefs.SetInt($"KeyBinding_{col}", (int)k); } PlayerPrefs.SetInt(SecondaryTrack3PrefsKey, (int)secondaryTrack3Key); PlayerPrefs.Save(); } private static void LoadKeyBindings() { keyBindings.Clear(); for (int i = 0; i < colors.Length; i++) { string col = colors[i]; if (PlayerPrefs.HasKey($"KeyBinding_{col}")) { keyBindings[col] = (KeyCode)PlayerPrefs.GetInt($"KeyBinding_{col}"); } else { keyBindings[col] = defaultKeys[i]; } } if (PlayerPrefs.HasKey(SecondaryTrack3PrefsKey)) { secondaryTrack3Key = (KeyCode)PlayerPrefs.GetInt(SecondaryTrack3PrefsKey); } else { secondaryTrack3Key = KeyCode.V; PlayerPrefs.SetInt(SecondaryTrack3PrefsKey, (int)secondaryTrack3Key); PlayerPrefs.Save(); } initialized = true; Debug.Log("KeyBindings 初始化成功:" + string.Join(", ", keyBindings)); } // Return a human-friendly display string for a KeyCode (symbols shown as their character) public static string GetDisplayName(KeyCode key) { if (key == KeyCode.Space) return "Space"; switch (key) { case KeyCode.Quote: return "'"; // single quote case KeyCode.Semicolon: return ";"; case KeyCode.Comma: return ","; case KeyCode.Period: return "."; case KeyCode.Slash: return "/"; case KeyCode.Backslash: return "\\"; case KeyCode.LeftBracket: return "["; case KeyCode.RightBracket: return "]"; case KeyCode.Minus: return "-"; case KeyCode.Equals: return "="; case KeyCode.BackQuote: return "`"; case KeyCode.Keypad0: return "Num0"; case KeyCode.Keypad1: return "Num1"; case KeyCode.Keypad2: return "Num2"; case KeyCode.Keypad3: return "Num3"; case KeyCode.Keypad4: return "Num4"; case KeyCode.Keypad5: return "Num5"; case KeyCode.Keypad6: return "Num6"; case KeyCode.Keypad7: return "Num7"; case KeyCode.Keypad8: return "Num8"; case KeyCode.Keypad9: return "Num9"; default: // For letters and named keys, use ToString(); for better readability, split "Alpha0" -> "0" string s = key.ToString(); if (s.StartsWith("Alpha") && s.Length > 5) return s.Substring(5); return s; } } }