FIX: handled events still triggering actions when switching PlayerInput#2340
FIX: handled events still triggering actions when switching PlayerInput#2340AswinRajGopal wants to merge 8 commits intodevelopfrom
Conversation
PR Reviewer Guide 🔍(Review updated until commit 8c58fe7)Here are some key observations to aid the review process:
🤖 Helpful? Please react with 👍/👎 | Questions❓Please reach out in Slack #ask-u-pr |
PR Code Suggestions ✨🤖 Helpful? Please react with 👍/👎 | Questions❓Please reach out in Slack #ask-u-pr |
Codecov ReportAttention: Patch coverage is
@@ Coverage Diff @@
## develop #2340 +/- ##
===========================================
+ Coverage 77.95% 77.97% +0.01%
===========================================
Files 476 476
Lines 97453 97526 +73
===========================================
+ Hits 75971 76044 +73
Misses 21482 21482
Flags with carried forward coverage won't be shown. Click here to find out more.
... and 1 file with indirect coverage changes 🚀 New features to boost your workflow:
|
Test Plan
Summary of Changes & Risk AssessmentSummary of ChangesThis PR fixes a bug where physical button presses that generate multiple input events (common on controllers like DualSense) would still trigger actions even if the first event was marked as Risk Assessment
Test ScenariosFunctional Testing
Regression Testing
🔍 Regression Deep Dive (additional risks identified)
Edge Cases
💡 This test plan updates automatically when 🤖 Helpful? Please react with 👍/👎 | Questions❓Please reach out in Slack #ask-u-pr |
…n child objects" This reverts commit ee9aace.
|
Persistent review updated to latest commit 94564dc |
| new int[] { 0, 0, 0, 0, 1}, // started | ||
| new int[] { 0, 0, 0, 0, 1}, // performed | ||
| new int[] {0, 0, 0, 0, 0})] // cancelled | ||
| // Press event is not detected in step 1/2 with default interaction | ||
| [TestCase(InputEventHandledPolicy.SuppressActionEventNotifications, | ||
| null, | ||
| new int[] { 0, 0, 0, 0, 1}, | ||
| new int[] { 0, 0, 0, 0, 1}, | ||
| new int[] {0, 0, 0, 1, 1})] | ||
| // Press event is detected in step 2 (false positive) with explicit press interaction | ||
| // Press event is suppressed in step 1/2 with explicit press interaction | ||
| [TestCase(InputEventHandledPolicy.SuppressStateUpdates, | ||
| "press", | ||
| new int[] { 0, 0, 1, 1, 2}, | ||
| new int[] { 0, 0, 1, 1, 2}, | ||
| new int[] {0, 0, 0, 1, 1})] | ||
| new int[] { 0, 0, 0, 0, 1}, | ||
| new int[] { 0, 0, 0, 0, 1}, | ||
| new int[] {0, 0, 0, 0, 0})] |
There was a problem hiding this comment.
This looks like a behavior change. What is the reason to change this?
There was a problem hiding this comment.
We needed a explicit way to keep action suppression working across update steps. It will ensure that actions doesn't trigger on next update which shows up as a false positive press like reported in the bug. Please correct me if I'm wrong - my understanding is,
- With
SupressStateUpdates, a handled press should not create started or performed in steps 1 or 2. - This change is removing the 2nd step false positive press and keeps the policy intact.
There was a problem hiding this comment.
I see. I'll keep looking at it to see if I find any problems. Meanwhile maybe @ekcoh has a more immediate answer since he added these tests.
…ed(...) and no longer early-exit the event loop when eventPtr.handled is set
|
Persistent review updated to latest commit 8c58fe7 |
|
Did not forget this one, still looking into it |
Pauliusd01
left a comment
There was a problem hiding this comment.
LGTM: Checked using the user project as well as our gamepad related sample scenes. Tried switching between mouse/keyboard/multiple gamepads in player and playmode, tried disconnecting/reconnecting as well as some of AI generated tests although those were a little bit "out there" and inconclusive. (Multiple listeners, Device switching, CrossUpdate supression, Rebinding supression) If there's anything specific you need me to recheck or you make changes after this then feel free to re-request the review
| } | ||
| } | ||
|
|
||
| var currentEventPtr = new InputEventPtr(currentEventReadPtr); |
There was a problem hiding this comment.
I'm wondering if we need to cache this explicitly or if doing it the previous way is enough, by using currentEventReadPtr ? I don't see a reason but maybe I'm missing something.
|
Thanks for looking into this @AswinRajGopal and creating this PR.
A device like DualSense is often served by a polling (sampling) backend. It means it continuously reads its state and hence generate many events. It is true the handled flag only stops one event, but one should not stop any event from the perspective to update device state (this will break by design - which is why I added suppress mode originally since the original behaviour doesn't make any sense IMO). But if the transition from false, (suppressed), true yields a press interaction event we are already overboard. This is the exact same problem as @MorganHoarau is currently working with from the perspective of rotating a screen. Hence I believe this is a RCS/RCA issue again about false positives. I need to look into the diff here to say more but just wanted to mention this. I suspect the root cause for this issue lies in InputActionState if it allows interaction state to update when previous state was consumed/suppressed.
This goes against the previous statement a bit. If there was a transition from false to true and true was suppressed, the following true should not be seen as a transition, since the transition is really true to true which is not a change. These two comments aside, I agree with you if you concluded that you wanted to change suppression mode. This is problematic since it would lead to a behavioural change. I initially struggle to see why test case asserts would change though. I need some more time to give better feedback on this PR and analyse it properly. |
| new int[] { 0, 0, 1, 1, 2}, // started | ||
| new int[] { 0, 0, 1, 1, 2}, // performed | ||
| new int[] {0, 0, 0, 1, 1})] // cancelled | ||
| new int[] { 0, 0, 0, 0, 1}, // started |
There was a problem hiding this comment.
If any of this changes I suspect it will regress the rebinding sample.
Description
Bug: https://issuetracker.unity3d.com/issues/setting-inputeventptr-dot-handled-to-true-does-not-prevent-actions-from-triggering-when-changing-devices
When
InputUser.onUnpairedDeviceUsedmarkseventPtr.handled= true, we expect no action to fire from that samebutton press.
But on devices like DualSense, a single press can generate multiple input events. The handled flag only stops the
one event, and another event in the same press still triggers the action.
Root cause
The action system is driven by state change events. We can see different eventIds for the handled event vs the
action‑triggering event, so the action was coming from a separate input event.
Fix
InputSystem.onEvent, stop calling remaining listeners once handled becomes true.for the rest of the update (and next update).
InputActionState, skip processing control changes if the device is suppressed.Testing status & QA
Manually verified using repro project + dualsense controller.
Overall Product Risks
Comments to reviewers
SuppressStateUpdatesand a listener explicitly sets handled = true.the next event look like a new press which is now prevented.
Checklist
Before review:
Changed,Fixed,Addedsections.Area_CanDoX,Area_CanDoX_EvenIfYIsTheCase,Area_WhenIDoX_AndYHappens_ThisIsTheResult.During merge:
NEW: ___.FIX: ___.DOCS: ___.CHANGE: ___.RELEASE: 1.1.0-preview.3.