InputHandlers: both ButtonDown and ButtonHeld are called

When using a XButtonHeld handler while a XButtonDown handler is also active, both get called.

I personally would expect that the XButtonDown call wouldn't fire if there's also a XButtonHeld handler and the button has been held for some minimum amount of ms time.

If for example a game used "hold B to open Map" and "press B to jump" ... every time the player went to hold B to open their map, their character would first jump once. Not terrible, but I'm sure there are other examples that could directly impact gameplay.

I could get around this by using XButtonUp of course, but that won't work for this specific app. The other option is to always have an empty XButtonDown pushed to the stack whenever this XButtonHeld is needed, but that seems vaguely hacky?

I can't decide if this feels intended (maybe?) or if it's a subtle bug.

But what if you hold down B until just before the BButtonHeld triggers? Then neither would happen.

I would argue that the behaviour is as it should be, and you just need to code it to do what you want or are expecting.

1 Like

Interesting. I mean if I think about it, that's actually what I would expect it to do. Like any game that requires you to hold to confirm some significant choice (every skill tree now does this). Thinking of Ghost since I played it recently, which uses this type of action often, both in UI and in gameplay:

Fair enough, can't argue with that logic :sweat_smile:

Not a big issue, it's just interesting to note that XButtonHeld can never be called independently, using it will always also include a call to XButtonDown preceding it and a XButtonUp following it.

What does this game do with a single press?

You're binding both press and hold, right?
Or am I misunderstanding the situation?

Some games in the season have what you're describing. Racheteer is one that springs to mind. @shaun how did you approach this?

Yeah that's the idea. Tapping B cycles through a stack of open UI windows, while holding B allows you to move the current window. I've added some small state management to handle it for now, but before that the B tap would cycle the window before you're able to do the hold action on it.

The best example I guess would be if you're opening a chest, you have to hold L2 for a moment. And if you're not near a chest, L2 aims your Bow instead. It would be strange if when you go to open the chest, first you briefly aim your Bow while you're waiting for the L2 chest UI button to fill up and open.

Maybe a more simple 2D example would be a theoretical platformer with some player ability on B. If you press B it fires the ability, and if you hold B it charges it and then fires it on B release. I'd expect it to not fire the ability once before I'm choosing to hold and charge it. As you said though, maybe you'd just need to code around the inputHandlers to work this way.


Anyway, I realize it may be equally as weird to ask that the XButtonDown get ignored if XButtonHeld is called immediately after it or something? So I guess I'm mostly just curious how others have dealt with it. I haven't gotten to Racheteer yet in my season, but would definitely be curious to see that.

1 Like

AFAIK, the typical (and maybe only?) way is to perform the “tap” action on button up, but only if button held hasn’t been called.

I can’t think of any logical way for the software to know whether the user is or isn’t going to hold a button, until either: they’ve held the button down the specified duration, or they let the button up in less than that duration.