防止热键重叠 [Unity]
Posted
技术标签:
【中文标题】防止热键重叠 [Unity]【英文标题】:Prevent Hotkeys Overlapping [Unity] 【发布时间】:2021-10-29 14:47:30 【问题描述】:我编写了一个“热键”类,它可以使用一些修饰键(shift、ctrl、cmd...)轻松评估单个给定键。
这个类能够像任何其他KeyControl
一样判断热键是被按下还是在当前帧上被按下/释放。当这些事情发生时,也能够发出 C# 事件。
代码就像一个魅力,除了一件事,例如,如果我想检查热键Ctrl+Z
,我会创建这样的实例:var ctrlZ = new Hotkey(Key.Z, ModifierKeys.LeftShift);
(Key
是一个 Unity 枚举,ModifierKeys
是一个标记自定义枚举,它定义了最常用的修饰键)。
然后,要检查它,我只需要致电:if (ctrlZ.isPressed) // code here...
问题来了,例如,当我按下组合 Ctrl+Shift+Z
时,上面的代码在我不希望它的时候评估为 true,因为我需要用 Ctrl+Z
热键做一件事,而另一个用Ctrl+Shift+Z
(重叠)。
我正在使用新的输入系统,并且,为了评估热键,我只是遍历修饰符 KeyControl
对象的列表,并检查它们是否与给定的 Key
同时按下。
那么问题是:我怎样才能防止这种重叠?
我尝试了最基本的解决方案,即将所有未使用的修饰符 KeyControl
对象添加到另一个列表并检查是否没有按下任何一个,但我想知道是否有比检查更简单有效的解决方案那样(它是在更新循环中完成的,因此,如果以这种方式评估许多热键,我认为它可能会导致一些开销)。
【问题讨论】:
【参考方案1】:虽然the docs 建议这不是由 Unity 完全实现的,因为它谈到了将左右移位组合成 shiftKey
的合成键,但没有与此相关的任何内容,但我认为有多种方法可以更好地实现这一点为您自己,也许通过直接挂钩到Keyboard
control 中的输入事件或扩展方法之一。
【讨论】:
在整个上午都在努力思考另一种解决方案之后,我决定保持原样。我通过每帧运行近 600 条指令来测试性能,经过的时间没有接近 0.3 毫秒,我认为这可以忽略不计。我尝试了你所说的并找出了方法,但它给了我同样的问题。无论如何感谢您的帮助!【参考方案2】:好吧,虽然我说我决定保留它在我对 Daniel Bereza 的评论中的样子,但我有最后一个想法,这似乎是我正在寻找的解决方案,而且它奏效了!
我决定自己回答,以防其他人需要解决此问题。
基本上,我所做的是检查每一帧是否按下了热键的修改键和是否没有按下其他任何键。这是通过 2 个循环完成的(一个用于需要按下的修饰符,另一个用于不需要按下的修饰符)。
为了替换那些循环,我使用了按位运算。诀窍是存储一个标记的枚举(在我的情况下为 ModifierKeys
类型),它告诉当前按下了哪些修饰键和另一个标记的枚举,它是互补的,可以说:private static ModifierKeys pressedModifiers
private static ModifierKeys unpressedModifiers
这两个字段是通过之前绑定到每个修改键的InputAction
事件更新的,所以当修改键被按下时,您将ModifierKey
标志添加到pressedModifiers
并同时更新补充unpressedModifiers
。
然后检查它是否被按下,例如,很简单:public bool IsPressed => modifiersToBePressed == pressedModifiers && ((int) (unpressedModifiers & modifiersToBePressed) == 0) && Keyboard.current[this.Key].isPressed
就是这样,如果您想检查它是否在当前帧上被按下或释放,只需将Keyboard.current[this.Key].isPressed
部分更改为您需要的任何内容。
我希望我已经很好地解释了自己。我对其进行了测试,它似乎按预期工作,除非有一些我没有考虑到的东西。我还测试了性能,而另一种方法平均需要 100-200 微秒来进行 600 次热键评估,但这种解决方法只需要 5-15 秒。这对我来说是一个很大的进步。
【讨论】:
以上是关于防止热键重叠 [Unity]的主要内容,如果未能解决你的问题,请参考以下文章