Enhanced Input has a design flaw(s): you cannot assign the same key twice to the same Input Action in the same Input Mapping Context

Well, actually, you CAN map the same key twice to the same Input Action in an Input Mapping Context. But it won’t work the way you think it should: the modifiers from both mappings will be applied, even if only one of them is triggered.

Now, let me explain how this problem appeared to me so that you don’t think I’m being silly for complaining about this.

I have an Input Action, IA_Move, that is bound to a function that moves a character some amount in all 3 dimensions. I have an Input Mapping Context that maps IA_Move to the WASD keys for forward, left, backward, and right movement, respectively, with the appropriate modifiers and triggers for this to work as expected. This works great for 2 dimensions of movement, but what about the third (up and down)? Well, I decided it would be convenient for my game if I didn’t have to move my hand very much to do that, so I wanted up and down movement to also be associated with the W and S keys, but only when the left-shift key is held down.

Immediately, you may notice that Enhanced Input does not appear to have any out-of-the-box support for multi-key mappings (another design flaw in my opinion, but not the point of this topic). My solution to this was to create an implicit trigger that only fires when another key is pressed, and a blocker trigger that also only fires when another key is pressed. Thus, I could add blocker trigger to my W and S mappings that modified the input to do Forward and Backward movement so that they did NOT fire when the left-shift key was down, and add the implicit trigger to different W and S mappings that modified the input to do Up and Down movement so that they ONLY fires when the left shift key was down.

Not too difficult, problem solved… right? Well, here is where we hit the problem I was talking about earlier. The custom triggers I wrote work correctly so that only one set of triggers ever fire in a given tick, however instead of only applying the modifiers associated with the same mapping as the trigger set that fired, the modifiers from both mappings end up getting applied. So when I press W, instead of going forward, I go forward AND up. And when I press left-shift+W, instead of going up, I also go forward AND up.

Why does this happen? Well, I can’t claim to know all the nuances of Enhanced Input, but I did look in the source code to see if I was doing something wrong, and I don’t see a way to get this solution to work with the current implementation of Enhanced Input. The problem is in UEnhancedPlayerInput::ProcessInputStack, which in turn calls UEnhancedPlayerInput::ProcessActionMappingEvent.

For some reason (maybe there’s a good one?), instead of evaluating the triggers, the first step taken in ProcessInputStack is to evaluate the modifiers of any mappings in the Input Mapping Context whose keys changed during the tick by calling ProcessActionMappingEvent. This seems wasteful to me from a performance perspective since you’re evaluating modifiers that may not be used, but I can ignore that because its probably an irrelevant amount of waste. The real problem is how the result of evaluating the modifiers is stored: in a TMap which uses the mapping’s Input Action as the key. This is the problem: the second mapping for that Input Action that uses the same key ends up reusing the same FInputActionInstance object when ProcessActionMappingEvent is called again, since that TMap cannot store multiple values (FInputActionInstance) for the same key (UInputAction).

So, in my case, when I press W or left-shift+W both my “Forward” and my “Up” mapping modifiers get applied, even though only one of their trigger sets fire. Again, it seems unnatural to me that modifiers would be evaluated and saved before evaluating the triggers.

Finally, I wanted to keep this topic focused on this specific problem with Enhanced Input, but I’m going to mention this anyways: even if this problem gets fixed, because there is no first-class support of mapping multiple keys (i.e. left-shift+W) to a single action, I’m pretty sure its going to very painful for me when I’m implementing a menu to allow users to rebind actions to multiple keys. Having to somehow dynamically manage these custom triggers or Input Mapping Contexts for each modifier key or whatever is gonna suck.

I would really appreciate it if the team working on Enhanced Input could put some consideration into these issues. And hopefully I didn’t just miss an obvious and easy solution to this and end up looking like a jackass.

1 Like

Have a look at what chorded action modifier does

I’m aware of them.

Chorded Action triggers sound useful if I have other Input Actions that make sense to chord with them. But what if I just have the one action that needs multiple keys? I need to create fake Input Actions that simply respond to the modifier key in order to use them?

Maybe I’m not fully understanding them. It doesn’t seem very intuitive or as useful as it should be to me.