在检查器中获取当前按下的键

Get currently pressed keys in inspector

我目前正在为我的 Unity 项目构建一个简单的快捷方式系统。

目前我正在通过字符串在检查器中插入快捷方式,例如:"Control+Alt+A"。但是每次都写太烦人了

所以我想为它创建一个自定义编辑器,其中文本框将自动填充用户按下的键。不幸的是,我发现获取此信息的唯一方法是使用 OnSceneGUI 函数,但它需要场景 window 具有焦点,并且如果快捷方式是在 Unity 中定义的,它将触发。

总而言之,如何读取当前按下的键并使用编辑器脚本显示它们?

编辑:this link 几乎可以满足我的需要,但它只检测到一个键(没有组合键),根本检测不到 Shift 键

很大程度上取决于您以后如何存储和检查热键,但您可以创建自定义的 EditorWindow 弹出窗口。

首先我会存储我的快捷方式,例如喜欢

[Serializable]
public struct ShortCut
{
    public bool Ctrl;
    public bool Alt;
    public bool Shift;

    public KeyCode Key;

    public ShortCut(KeyCode key, bool ctrl, bool alt, bool shift)
    {
        Key = key;
        Ctrl = ctrl;
        Alt = alt;
        Shift = shift;
    }

    public override string ToString()
    {
        var builder = new StringBuilder();
        if (Ctrl) builder.Append("CTRL + ");
        if (Alt) builder.Append("ALT + ");
        if (Shift) builder.Append("SHIFT + ");

        builder.Append(Key.ToString());

        return builder.ToString();
    }

    public bool IsDown => IsCtrlDown && IsAltDown && IsShiftDown && Input.GetKeyDown(Key);

    private bool IsCtrlDown => !Ctrl || Input.GetKey(KeyCode.RightControl) || Input.GetKey(KeyCode.LeftControl);
    private bool IsAltDown => !Alt || Input.GetKey(KeyCode.LeftAlt) || Input.GetKey(KeyCode.RightAlt);
    private bool IsShiftDown => !Shift || Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift);
}

您可以在脚本中等待它,例如

public class ShortCutTester : MonoBehaviour
{
    // This youc an now call via the context menu of the someShortCut field in the Inspector
    [ContextMenuItem("Set Shortcut", nameof(SetSomeShortCut))]
    public ShortCut someShortCut;

    private void SetSomeShortCut()
    {
        ShortKeyDialog.ShowDialog(someShortCut, result =>
        {
            // mark as dirty and provide undo/redo funcztionality
            Undo.RecordObject(this, "Change someShortCut");
            someShortCut = result;
        });
    }

    private void Update()
    {
        if (someShortCut.IsDown)
        {
            Debug.Log("Hello!");
        }
    }

    #if UNITY_EDITOR
    // in order to catch all editor own key events on runtime
    // you will still get the warning "You have to exit playmode in order to save"
    // but at least this makes the Hello print anyway. Couldn't figure out how to catch the key completely before Unity handles it
    private void OnGUI()
    {
        var e = Event.current;
        e.Use();
    }
    #endif
}

并通过弹出对话框进行设置

public class ShortKeyDialog : EditorWindow
{
    private ShortCut keys;
    private ShortCut newKeys;
    private Action<ShortCut> callback;
    private bool changed;

    public static void ShowDialog( ShortCut currentShortcut, Action<ShortCut> onDone)
    {
        var dialog = GetWindow<ShortKeyDialog>();
        dialog.keys = currentShortcut;
        dialog.newKeys = currentShortcut;
        dialog.callback = onDone;
        dialog.minSize = new Vector2(300, 200);
        dialog.position = new Rect(Screen.width / 2f + 150, Screen.height / 2f + 100, 300, 200);
        dialog.ShowModalUtility();
    }

    private void OnGUI()
    {
        //Get pressed keys
        var e = Event.current;
        if (e?.isKey == true)
        {
            switch (e.type)
            {
                case EventType.KeyDown:
                    switch (e.keyCode)
                    {
                        // Here you will need all allowed keycodes
                        case KeyCode.A:
                        case KeyCode.B:
                        case KeyCode.C:
                        case KeyCode.D:
                        case KeyCode.E:
                        case KeyCode.F:
                        case KeyCode.G:
                        case KeyCode.H:
                        case KeyCode.I:
                        case KeyCode.J:
                        case KeyCode.K:
                        case KeyCode.L:
                        case KeyCode.M:
                        case KeyCode.N:
                        case KeyCode.O:
                        case KeyCode.P:
                        case KeyCode.Q:
                        case KeyCode.R:
                        case KeyCode.S:
                        case KeyCode.T:
                        case KeyCode.U:
                        case KeyCode.V:
                        case KeyCode.W:
                        case KeyCode.X:
                        case KeyCode.Y:
                        case KeyCode.Z:
                        case KeyCode.F1:
                        case KeyCode.F2:
                        case KeyCode.F3:
                        case KeyCode.F4:
                        case KeyCode.F5:
                        case KeyCode.F6:
                        case KeyCode.F7:
                        case KeyCode.F8:
                        case KeyCode.F9:
                        case KeyCode.F10:
                        case KeyCode.F11:
                        case KeyCode.F12:
                        case KeyCode.F13:
                        case KeyCode.F14:
                        case KeyCode.F15:
                        case KeyCode.Comma:
                        case KeyCode.Plus:
                        case KeyCode.Minus:
                        case KeyCode.Period:
                            // etc depends on your needs I guess
                            changed = true;
                            newKeys = new ShortCut (e.keyCode, e.control, e.alt, e.shift);

                            // Refresh the EditorWindow
                            Repaint();
                            break;
                    }
                    break;
            }

            // Use all key presses so nothing else handles them 
            // e.g. also not the Unity editor itself like e.g. for CTRL + S
            e.Use();
        }

        EditorGUILayout.LabelField("Current Shortcut");
        EditorGUILayout.HelpBox(keys.ToString(), MessageType.None);

        EditorGUILayout.Space();

        EditorGUILayout.LabelField("Press buttons to assign a new shortcut", EditorStyles.textArea);

        EditorGUILayout.HelpBox(newKeys.ToString(), MessageType.None);

        EditorGUILayout.Space();

        EditorGUILayout.BeginHorizontal();
        {
            if (GUILayout.Button("Cancel"))
            {
                Close();
            }
            EditorGUI.BeginDisabledGroup(!changed);
            {
                if (GUILayout.Button("Save"))
                {
                    callback?.Invoke(newKeys);
                    Close();
                }
            }
            EditorGUI.EndDisabledGroup();
        }
        EditorGUILayout.EndHorizontal();
    }
}

请注意:在智能手机上打字,所以目前没有机会测试和更正一些东西,但我希望这个想法变得清晰

返回 PC 后会尽快测试和更新