How to implement keyboard shortucts that send events to ui elements without having them focused?

Consider games like League of Legends (and I suppose most, if not all ARPGs).

It is common that they have an ability bar on their HUD. When an ability icon is clicked then the player character will perform the associated ability. I suppose that since ability icons are a part of the HUD then implementing them as VisualElements would be a good idea.

Since I’m trying to learn, Unity itself suggested this to me and in the future I’d like to implement control rebinding I thought I’d also use the Input System package. I managed to implement this without big troubles. As per the documentation I added the EventSystem and InputSystemUIInputModule components to the scene; I also added an Input Action asset and referenced this asset from the InputSystemUIInputModule component. Unity set up sensible defaults for me so that I could just register clicked event handlers on my abilities from C# code:

using UnityEngine.UIElements;

public class AbilityBarManager : MonoBehaviour
{
    private void Awake()
    {
       UIDocument  uiDocument = GetComponent<UIDocument>();
        Button fireballButton = uiDocument.rootVisualElement.Q<Button>(name: "FireBall");
        fireballButton.clicked += () => { Player.instance.CastFireBall(); };
    }
}

(for simplicity I omit code responsible for managing cooldowns, etc)

(Also yes, I made the Player MonoBehaviour class a singleton, not sure if this makes sense but hey, at least it works)

But having to rely on mouse clicks is not acceptable. The player should be able to cast abilities without necessarily having to click on the ability button. For this reason multiple games provide keyboard shortcuts. During normal gameplay, without having to focus the ability button, the player should be able to cast a fireball by, for example, pressing Q on their keyboard.

And at this point I’m stuck.

I tried looking in the documentation, but to no avail.

First, I found this docu page: Unity - Manual: Keyboard events But this won’t support rebinding without some manual work and, to my understanding, it also depends on the button being focused, which is not acceptable here.

Then I found this docu page: On-screen Controls | Input System | 1.4.4 It looks promising, but it seems to me it requires the use of UGUI even though Input System is supposed to be compatible with UI Toolkit.

How to send an event to a GUI element when an arbitrary keyboard button is pressed?

Usually, these kinds of keyboard shortcuts are not implemented as a message sent to a UI Element. You’re suggesting a hierarchy of responsibilities where the shortcut somehow triggers an event on a non-focused VisualElement, which then runs some code. It’s probably better to remove the VisualElement as an intermediary for shortcut interactions and just have a method that is executed both in reaction to the shortcut and in reaction to mouse interactions with the UI.

2 Likes

Well it’s nice thing to have (a gui element reaction to some hotkey press) because it allows you to have the same visual feedback as if you pressed down a button with a mouse pointer. I don’t mean that a gui button itself should support input handling, but it must allow us to manually simulate it’s visual state at least, either with some intended mecanism for it or with a temp USS change there and back for example.

I think this is covered by the ability to add and remove USS classes from elements. I’m not saying this is as simple as it can be, although I struggle to imagine how it could be simpler. Maybe there could be an API that adds a USS class and removes it after a some user-defined time.