Axis motion axis does not change when two buttons are pressed simultaneously

I’m using Enhanced Input to control the character’s movement. I followed the tutorial. I got it right, when I press W (axis +1) the character goes forward, when I press S (axis -1) the character goes backwards. When I first press the button W, and then simultaneously pressed S, the character starts to go backwards, as this button I pressed last (this is correct). But when I first press S and then W, the character does not go forward, and continues to go backwards. For some reason in this situation axis is not reversed (as in the case of the first pressed W and then S).I want the character to go in the same way in the direction of the last pressed button.

Thanks for the question, this is something a nice catch from your side.

When i look a bit into engine code and how input accumulation is made on “TakeHighestAbsoluteValue” in input settings.

FVector Modified = ModifiedValue.Get<FVector>();
FVector Merged = ActionData.Value.Get<FVector>();
...
case EInputActionAccumulationBehavior::TakeHighestAbsoluteValue:
default:
if (FMath::Abs(Modified[Component]) >= FMath::Abs(Merged[Component]))
					{
						Merged[Component] = Modified[Component];
					}	

as we can see when accumulation behaviour is take highest since values are merged and continues and since the back have a negate modifier it stays. We can write a new accumulation behaviour in low level engine code or have modifiers on top of it.

However both solutions are engine modification and even a not unified solutions since on the tick we have to last input vector value so we have to know what is changed on that tick and what player is trying to do. So have to change some mindset in order to have a better ux targeted.

We have to know which input cardinal is pressed last, we can write this again in low level input or movement however in blueprints a simple logic can be created like below.

What is happening here?

  • For Cardinal W/S I made 2 digital inputs.So I can have distinction between them.
  • OnStarted I use an Array to record which inputs in charge, add them to array. Which is first Which is last.
  • OnComplete, I find the completed action and remove it.
  • So I know which input is last and if last input equals to forward → Select 1 else -1
  • GiveForwardVector to Triggers since they are running on same tick there is nothing to worry as concept.

This will achieve what you expect, last input from player changes direction no matter which key is hold, unless key is pressed again. It works nicely in KBM setup.

Couple of headsup

  • Test with different hardware that is targeted for your game.
  • There could be some other needs with analog inputs, this is designed for digital input
  • There could be some other needs with analog inputs, if you have some specific movements like 2 stick setups.
  • This is sometimes used as a cheat in some games and keyboard actuations. Like mine Razar Huntsman v3 with optical sensors, can be sometimes cause combat frustration between players.
  • In short TEST and Use with Caution :warning:

After also digging around, an engine modification can be made for this however its not the best scenario and its just overkill.

A custom input modifier class works for this, we can get last input and hold it however it has one major problem which is release events.. So it is not the best choice.

No need to re invent the wheel to be honest, if you need to specifically use 2D Axis the solution/hack demonstrated above would work, keeping the last input in charge. However I would have gone with WSAD digital inputs and record them as cardinals, get last inputs on cardinals and make input vector.

That would be the best concrete movement of what is desired always last input on cardinal axis considered in charge like below

results