GameInput digipad rapidly triggering started/completed while keeping the button pressed.

Using the enhanced input system

  • IA_Lookup (all on default)
  • IMC_Default mapping IA_Lookup to three things: A keyboard-key (let’s assume “L”), the “Square” on the PS5 controller, the “Digipad-Up”.
  • Using UE5.7 from source, with GameInput SDK + runtime installed.
  • Plugins “Game Input Base” and “Game Input (Windows)” enabled, disabled “XInput”.
  • EnhancedInputAction IA_Lookup placed in the player blueprint, reacting to “Started” (instruct character to look up) and “Completed” (instruct character look forward).

InputSettings.ini

[GameInputPlatformSettings_Windows GameInputPlatformSettings]
bProcessController=True

[/Script/GameInputBase.GameInputDeveloperSettings]
+DeviceConfigurations=(DeviceIdentifier=(VendorId=1356,ProductId=3302),Description=“PS5 DualSense controller”,bOverrideHardwareDeviceIdString=True,OverriddenHardwareDeviceId=“DualSense”,bProcessControllerButtons=True,bProcessControllerSwitchState=True,bProcessControllerAxis=True,ControllerButtonMappingData=((1, “Gamepad_FaceButton_Left”),(2, “Gamepad_FaceButton_Bottom”),(4, “Gamepad_FaceButton_Right”),(8, “Gamepad_FaceButton_Top”),(16, “Gamepad_LeftShoulder”),(32, “Gamepad_RightShoulder”),(64, “Gamepad_LeftTrigger”),(128, “Gamepad_RightTrigger”),(256, “Gamepad_Special_Left”),(512, “Gamepad_Special_Right”),(1024, “Gamepad_LeftThumbstick”),(2048, “Gamepad_RightThumbstick”),(8192, “Gamepad_Special_Left”)),ControllerAxisMappingData=((0, (KeyName=“Gamepad_LeftX”,DeadZone=0.239532,bIsPackedPositveAndNegative=True)),(1, (KeyName=“Gamepad_LeftY”,Scalar=-1.000000,bIsPackedPositveAndNegative=True)),(2, (KeyName=“Gamepad_RightX”,bIsPackedPositveAndNegative=True)),(3, (KeyName=“Gamepad_LeftTriggerAxis”)),(4, (KeyName=“Gamepad_RightTriggerAxis”,DeadZone=0.239532)),(5, (KeyName=“Gamepad_RightY”,Scalar=-1.000000,bIsPackedPositveAndNegative=True))))

When clicking on the “mapping” icon in the IMC, and pressing a button on the controller, it does correctly map it (so GameInput is working).

Nor running the game, I observing the following:

When pressing :

  • the key, my characters looks up, as long as the key is pressed (correct).
  • the “Square” on the gamepad, the character looks up as long as pressed.
  • the “Digipad-up” on the gamepad, the first time pressing the character looks up (as long as pressed) and on releasing the character looks back forward. So far perfect. However when now pressing the Digipad-up again, the character rapidly toggles between looking up and forward- because there is a rapid flow of “Started” and “Completed” events firing.

Why is it so specific to the digipad buttons?
Any ideas where to look?

Update: Created a new FirstPerson shooter template with 5.6, updated to locally built 5.7, enabled the two gameinput plugins, disabled xinput, enabled processing of the gamecontroller in the plugin gameinput settings, mapped an IA to process the dpad-up, changed the bp_firstpersoncharacter to just do print strings on started and completed. Press & hold the first time, 1x “started”, releasing the button “completed”. Now press & hold again - it keeps rapidly printing the debug-strings,. toggling between them (expected: printing “started” exactly once, until released).

Noticed the option “Process Controller Switch State”, which specifically mentions you might want to disable it, if the dpad is processed as buttons already. Disabled it - pressing it in the game, no reaction anymore.

Also, Game Input for Windows - Experimental Release Notes | Tutorial has a definition for the ps5 controller with (256, “Gamepad_Special_Left”) and also (8192, “Gamepad_Special_Left”) which is a bit suspicious.

This sounds different, but is similar in them mentioning that the first time it works.

Update2:

Just noticed that each time after a focus switch (ALT+TAB) out and back into the window, the button will behave correct 1 time - and after that will repeat again even if being held.

It seems the D-pad on GameInput is being treated as both a switch and button input, which could explain the rapid firing of Started/Completed. Disabling “Process Controller Switch State” stops the input completely because the mapping is then lost. Might be worth checking whether only one of those states can be mapped manually in the ControllerButtonMappingData.

You mean changing the definition in the DefaultInput.xml? I’m wondering about that, because it doesn’t look like the dpad buttons are part of the definition in the current state (so how can it react to the dpad at all?!)…

I think I can actually get this situation in the debugger, by running the game, switching to visual studio and now pressing the gamepad buttons - where the window reacts without triggering a focus switch, and then setting breakpoints. Then doing press & release “up-dpad” (1st time works) and then pressing up-dpad and holding it to get into the problematic situation.

GameInput sometimes treats the d-pad press as start and complete events on every frame instead of holding it down. Updating to the latest GameInput SDK usually helps, but if it still happens the workaround is to check the IsPressed state for the button rather than relying only on started and completed events. That way it behaves like a proper hold instead of spamming triggers.

So some more details, setting a breakpoint in UEnhancedPlayerInput::GetTriggerStateChangeEvent on the line with “return ETriggerEventInternal::Completed;” getting into the broke situation and then going back in the callstack we see the following:

  • LastTriggerState = Triggered
  • TriggerEventInternal = Triggered
  • TriggerEvent = Triggered
  • It skipped over the ActionsWithEventsThisTick if-statement, so “ETriggerState TriggerState = ETriggerState::None;” is still at its default of “None” - which is what makes the call where we put the breakpoint evaluate to “Completed”.

Now if we set a breakpoint inside that if-statement, we alt-tab to get a fresh windowfocus-switch so the dpad-up works the first time, and then we push it (the first time) indeed it does go into that if-statement and the character does look up! And after that, it’ll skip the if.

So for some reason ActionsWithEventsThisTick only contains the action the first time, and is broken until we get another windowfocus-switch which resets the situation.

Out of curiousity I’ll try and backtrack how ActionsWithEventsThisTick is filled, and if that doesn’t lead anywhere I’ll try the suggested approach of checking for IsPressed (and be a bit disappointed that handling input is still problematic compared to 20+ years ago - why doesn’t this stuff “just work” :frowning: )