Skip to content

Commit fcc3891

Browse files
authored
FIX: Disconnecting a device while an input is active should not throw (#1427)
1 parent 3d0dcad commit fcc3891

File tree

3 files changed

+34
-3
lines changed

3 files changed

+34
-3
lines changed

Assets/Tests/InputSystem/CoreTests_Actions_Interactions.cs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System.Linq;
22
using NUnit.Framework;
3+
using NUnit.Framework.Constraints;
34
using UnityEngine;
45
using UnityEngine.InputSystem;
56
using UnityEngine.InputSystem.Interactions;
@@ -793,4 +794,21 @@ public void Actions_ValueIsDefaultWhenActionIsCanceled()
793794
Assert.That(canceledCount, Is.EqualTo(1));
794795
Assert.That(canceledValue, Is.EqualTo(0.0));
795796
}
797+
798+
// https://fogbugz.unity3d.com/f/cases/1354098/
799+
[Test]
800+
[Category("Actions")]
801+
public void Actions_DoesNotThrowWhenDeviceIsDisconnectedWhileControlIsPressed()
802+
{
803+
var gamepad = InputSystem.AddDevice<Gamepad>();
804+
805+
var action = new InputAction("Action",
806+
binding: "<Gamepad>/buttonSouth",
807+
interactions: "Press,Press"); // this bug occurs when there are multiple interactions on a binding
808+
action.Enable();
809+
810+
Press(gamepad.buttonSouth);
811+
812+
Assert.That(() => InputSystem.RemoveDevice(gamepad), Throws.Nothing);
813+
}
796814
}

Packages/com.unity.inputsystem/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ however, it has to be formatted properly to pass verification tests.
2626
- Generic gamepad short display button names where incorrectly mapped on Switch (`A` instead of `B`, etc).
2727
- Fixed an issue where resetting an action via `InputAction.Reset()` while being in disabled state would prevent the action from being enabled again. ([case 1370732](https://issuetracker.unity3d.com/product/unity/issues/guid/1370732/)).
2828
- Fixed "Default constructor not found for type UnityEngine.InputSystem.iOS.LowLevel.iOSStepCounter" any other potential exceptions due to classes, methods, fields and properties being stripped when managed stripping setting set to medium or high ([case 1368761](https://issuetracker.unity3d.com/issues/ios-new-input-system-iosstepcounter-crash-on-launch-with-managed-stripping)).
29+
- Fixed an issue where InvalidOperationExceptions are thrown if an input for an action with multiple interactions is held while disconnecting the device([case 1354098](https://issuetracker.unity3d.com/issues/input-system-errors-are-thrown-when-disconnecting-controller-while-holding-a-button-with-press-and-release-set-up-separately)).
2930
- Fixed `action.ReadValue` and others returning invalid data when used from `FixedUpdate` or early update when running in play mode in the editor ([case 1368559](https://issuetracker.unity3d.com/issues/enter-key-is-not-registered-when-using-waspressedthisframe-with-input-system-1-dot-1-1) [case 1367556](https://issuetracker.unity3d.com/issues/input-action-readvalue-always-returns-zero-when-called-from-fixedupdate) [case 1372830](https://issuetracker.unity3d.com/issues/querying-inputs-before-preupdate-dot-newinputupdate-returns-invalid-data-when-running-in-play-mode-in-editor)).
3031

3132
### Added

Packages/com.unity.inputsystem/InputSystem/Actions/InputActionState.cs

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1690,6 +1690,9 @@ private void StopTimeout(int mapIndex, int controlIndex, int bindingIndex, int i
16901690
/// <see cref="InputActionPhase.Waiting"/> (default), <see cref="InputActionPhase.Started"/> (if the action is supposed
16911691
/// to be oscillate between started and performed), or <see cref="InputActionPhase.Performed"/> (if the action is
16921692
/// supposed to perform over and over again until canceled).</param>
1693+
/// <param name="processNextInteractionsOnCancel">Indicates if the system should try and change the phase of other
1694+
/// interactions on the same action that are already started or performed after cancelling this interaction. This should be
1695+
/// false when resetting interactions.</param>
16931696
/// <remarks>
16941697
/// Multiple interactions on the same binding can be started concurrently but the
16951698
/// first interaction that starts will get to drive an action until it either cancels
@@ -1705,7 +1708,7 @@ private void StopTimeout(int mapIndex, int controlIndex, int bindingIndex, int i
17051708
/// long and the SlowTapInteraction will get to drive the action next).
17061709
/// </remarks>
17071710
internal void ChangePhaseOfInteraction(InputActionPhase newPhase, ref TriggerState trigger,
1708-
InputActionPhase phaseAfterPerformed = InputActionPhase.Waiting)
1711+
InputActionPhase phaseAfterPerformed = InputActionPhase.Waiting, bool processNextInteractionsOnCancel = true)
17091712
{
17101713
var interactionIndex = trigger.interactionIndex;
17111714
var bindingIndex = trigger.bindingIndex;
@@ -1753,6 +1756,9 @@ internal void ChangePhaseOfInteraction(InputActionPhase newPhase, ref TriggerSta
17531756
if (!ChangePhaseOfAction(newPhase, ref trigger))
17541757
return;
17551758

1759+
if (processNextInteractionsOnCancel == false)
1760+
return;
1761+
17561762
var interactionStartIndex = bindingStates[bindingIndex].interactionStartIndex;
17571763
var numInteractions = bindingStates[bindingIndex].interactionCount;
17581764
for (var i = 0; i < numInteractions; ++i)
@@ -1942,7 +1948,13 @@ private void ChangePhaseOfActionInternal(int actionIndex, TriggerState* actionSt
19421948
// We need to make sure here that any HaveMagnitude flag we may be carrying over from actionState
19431949
// is handled correctly (case 1239551).
19441950
newState.flags = actionState->flags; // Preserve flags.
1945-
newState.magnitude = trigger.haveMagnitude ? trigger.magnitude : ComputeMagnitude(trigger.bindingIndex, trigger.controlIndex);
1951+
if (newPhase != InputActionPhase.Canceled)
1952+
newState.magnitude = trigger.haveMagnitude
1953+
? trigger.magnitude
1954+
: ComputeMagnitude(trigger.bindingIndex, trigger.controlIndex);
1955+
else
1956+
newState.magnitude = 0;
1957+
19461958
newState.phase = newPhase;
19471959
if (newPhase == InputActionPhase.Performed)
19481960
{
@@ -2145,7 +2157,7 @@ private void ResetInteractionStateAndCancelIfNecessary(int mapIndex, int binding
21452157
{
21462158
case InputActionPhase.Started:
21472159
case InputActionPhase.Performed:
2148-
ChangePhaseOfInteraction(InputActionPhase.Canceled, ref actionStates[actionIndex]);
2160+
ChangePhaseOfInteraction(InputActionPhase.Canceled, ref actionStates[actionIndex], processNextInteractionsOnCancel: false);
21492161
break;
21502162
}
21512163
}

0 commit comments

Comments
 (0)