diff --git a/Packages/com.unity.inputsystem/CHANGELOG.md b/Packages/com.unity.inputsystem/CHANGELOG.md index 0cd08946ae..f8e32c4e35 100644 --- a/Packages/com.unity.inputsystem/CHANGELOG.md +++ b/Packages/com.unity.inputsystem/CHANGELOG.md @@ -11,6 +11,7 @@ however, it has to be formatted properly to pass verification tests. ## [Unreleased] - yyyy-mm-dd ### Fixed +- Fixed touch pointers being released twice causing an index out of bounds error. [ISXB-687](https://issuetracker.unity3d.com/product/unity/issues/guid/ISXB-687) - Fixed `NullReferenceException` from disconnecting and reconnecting a GXDKGamepad. ### Added diff --git a/Packages/com.unity.inputsystem/InputSystem/Plugins/UI/InputSystemUIInputModule.cs b/Packages/com.unity.inputsystem/InputSystem/Plugins/UI/InputSystemUIInputModule.cs index 7d61c3643f..c65c6a6700 100644 --- a/Packages/com.unity.inputsystem/InputSystem/Plugins/UI/InputSystemUIInputModule.cs +++ b/Packages/com.unity.inputsystem/InputSystem/Plugins/UI/InputSystemUIInputModule.cs @@ -1947,6 +1947,13 @@ private void RemovePointerAtIndex(int index) { Debug.Assert(m_PointerStates[index].eventData.pointerEnter == null, "Pointer should have exited all objects before being removed"); + // We don't want to release touch pointers on the same frame they are released (unpressed). They get cleaned up one frame later in Process() + ref var state = ref GetPointerStateForIndex(index); + if (state.pointerType == UIPointerType.Touch && (state.leftButton.isPressed || state.leftButton.wasReleasedThisFrame)) + { + return; + } + // Retain event data so that we can reuse the event the next time we allocate a PointerModel record. var eventData = m_PointerStates[index].eventData; Debug.Assert(eventData != null, "Pointer state should have an event instance!"); @@ -2209,7 +2216,13 @@ private void FilterPointerStatesByType() // We have input on a mouse or pen. Kill all touch and tracked pointers we may have. for (var i = 0; i < m_PointerStates.length; ++i) { - if (m_PointerStates[i].pointerType != UIPointerType.MouseOrPen) + ref var state = ref GetPointerStateForIndex(i); + // Touch pointers need to get forced to no longer be pressed otherwise they will not get released in subsequent frames. + if (m_PointerStates[i].pointerType == UIPointerType.Touch) + { + state.leftButton.isPressed = false; + } + if (m_PointerStates[i].pointerType != UIPointerType.MouseOrPen && m_PointerStates[i].pointerType != UIPointerType.Touch || (m_PointerStates[i].pointerType == UIPointerType.Touch && !state.leftButton.isPressed && !state.leftButton.wasReleasedThisFrame)) { SendPointerExitEventsAndRemovePointer(i); --i;