在检查器中获取当前按下的键
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 后会尽快测试和更新
我目前正在为我的 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 后会尽快测试和更新