C# 在inspector中获取当前按下的键
我目前正在为我的Unity项目构建一个简单的快捷方式系统 目前,我正在通过字符串在inspector中插入快捷方式,例如:Control+Alt+A。但是每次编写它都太烦人了 因此,我考虑为它创建一个自定义编辑器,其中文本框将自动填充用户按下的键。不幸的是,我发现获取此信息的唯一方法是使用OnSceneGUI函数,但它要求场景窗口具有焦点,如果在Unity中定义了快捷方式,则会触发 总之,我如何读取当前按下的键并用编辑器脚本显示它们C# 在inspector中获取当前按下的键,c#,unity3d,unity3d-editor,C#,Unity3d,Unity3d Editor,我目前正在为我的Unity项目构建一个简单的快捷方式系统 目前,我正在通过字符串在inspector中插入快捷方式,例如:Control+Alt+A。但是每次编写它都太烦人了 因此,我考虑为它创建一个自定义编辑器,其中文本框将自动填充用户按下的键。不幸的是,我发现获取此信息的唯一方法是使用OnSceneGUI函数,但它要求场景窗口具有焦点,如果在Unity中定义了快捷方式,则会触发 总之,我如何读取当前按下的键并用编辑器脚本显示它们 编辑:几乎可以满足我的需要,但它只检测到一个键,没有组合,而且
编辑:几乎可以满足我的需要,但它只检测到一个键,没有组合,而且根本检测不到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();
}
}
请注意:在智能手机上打字,所以目前没有机会测试和纠正问题,但我希望想法变得清晰
回到电脑上后会尽快测试和更新@BugFinder不是我需要的它工作正常,但我有两个问题;1什么是dialog.ShowModalUtility,它不编译。2有没有办法取消Unity中的快捷键呢?因为像Ctrl+S这样的快捷键也与Unity有关。请注意,我已经用我在问题中链接的脚本修复了这些问题。我会尽快更新我的问题,以包含正确和完整的代码。非常感谢你,你总是给出最好和最详细的回答,我刚刚修正了所有的打字错误和东西;现在再试一次工作正常,但dialog.ShowModalUtility仍无法编译.p.s。如果我想要一个快捷方式列表而不仅仅是一个,它还能工作吗