diff --git a/Packages/com.unity.inputsystem/CHANGELOG.md b/Packages/com.unity.inputsystem/CHANGELOG.md index b75bc0c0a4..98b6df8b90 100644 --- a/Packages/com.unity.inputsystem/CHANGELOG.md +++ b/Packages/com.unity.inputsystem/CHANGELOG.md @@ -16,6 +16,7 @@ however, it has to be formatted properly to pass verification tests. - Fixed wrong mapping of Xbox Series S|X and Xbox One wireless controllers "View" button on macOS.[ISXB-385](https://issuetracker.unity3d.com/product/unity/issues/guid/ISXB-385) - Fixed "AnalyticsResult" errors on consoles [ISXB-1107] - Fixed wrong `Display Index` value for touchscreen events.[ISXB-1101](https://issuetracker.unity3d.com/product/unity/issues/guid/ISXB-1101) +- Fixed event handling when using Fixed Update processing where WasPressedThisFrame could appear to true for consecutive frames [ISXB-1006](https://issuetracker.unity3d.com/product/unity/issues/guid/ISXB-1006) ### Added - Added the display of the device flag `CanRunInBackground` in device debug view. diff --git a/Packages/com.unity.inputsystem/InputSystem/Actions/InputAction.cs b/Packages/com.unity.inputsystem/InputSystem/Actions/InputAction.cs index e303f16570..f196465961 100644 --- a/Packages/com.unity.inputsystem/InputSystem/Actions/InputAction.cs +++ b/Packages/com.unity.inputsystem/InputSystem/Actions/InputAction.cs @@ -1236,7 +1236,7 @@ public unsafe bool WasPressedThisFrame() { var actionStatePtr = &state.actionStates[m_ActionIndexInState]; var currentUpdateStep = InputUpdate.s_UpdateStepCount; - return actionStatePtr->pressedInUpdate == currentUpdateStep && currentUpdateStep != default; + return actionStatePtr->pressedInUpdate == currentUpdateStep && currentUpdateStep != default && actionStatePtr->frame == Time.frameCount; } return false; @@ -1285,7 +1285,7 @@ public unsafe bool WasReleasedThisFrame() { var actionStatePtr = &state.actionStates[m_ActionIndexInState]; var currentUpdateStep = InputUpdate.s_UpdateStepCount; - return actionStatePtr->releasedInUpdate == currentUpdateStep && currentUpdateStep != default; + return actionStatePtr->releasedInUpdate == currentUpdateStep && currentUpdateStep != default && actionStatePtr->frame == Time.frameCount; } return false; @@ -1344,7 +1344,7 @@ public unsafe bool WasPerformedThisFrame() { var actionStatePtr = &state.actionStates[m_ActionIndexInState]; var currentUpdateStep = InputUpdate.s_UpdateStepCount; - return actionStatePtr->lastPerformedInUpdate == currentUpdateStep && currentUpdateStep != default; + return actionStatePtr->lastPerformedInUpdate == currentUpdateStep && currentUpdateStep != default && actionStatePtr->frame == Time.frameCount; } return false; @@ -1417,7 +1417,7 @@ public unsafe bool WasCompletedThisFrame() { var actionStatePtr = &state.actionStates[m_ActionIndexInState]; var currentUpdateStep = InputUpdate.s_UpdateStepCount; - return actionStatePtr->lastCompletedInUpdate == currentUpdateStep && currentUpdateStep != default; + return actionStatePtr->lastCompletedInUpdate == currentUpdateStep && currentUpdateStep != default && actionStatePtr->frame == Time.frameCount; } return false; diff --git a/Packages/com.unity.inputsystem/InputSystem/Actions/InputActionState.cs b/Packages/com.unity.inputsystem/InputSystem/Actions/InputActionState.cs index 3ba1503d49..cd17fdd942 100644 --- a/Packages/com.unity.inputsystem/InputSystem/Actions/InputActionState.cs +++ b/Packages/com.unity.inputsystem/InputSystem/Actions/InputActionState.cs @@ -560,6 +560,7 @@ private void RestoreActionStatesAfterReResolvingBindings(UnmanagedMemory oldStat newActionState.releasedInUpdate = oldActionState.releasedInUpdate; newActionState.startTime = oldActionState.startTime; newActionState.bindingIndex = oldActionState.bindingIndex; + newActionState.frame = oldActionState.frame; if (oldActionState.phase != InputActionPhase.Disabled) { @@ -884,6 +885,7 @@ public void ResetActionState(int actionIndex, InputActionPhase toPhase = InputAc actionState->lastCompletedInUpdate = default; actionState->pressedInUpdate = default; actionState->releasedInUpdate = default; + actionState->frame = default; } Debug.Assert(!actionState->isStarted, "Cannot reset an action to started phase"); @@ -1579,6 +1581,7 @@ private void ProcessButtonState(ref TriggerState trigger, int actionIndex, Bindi { actionState->pressedInUpdate = InputUpdate.s_UpdateStepCount; actionState->isPressed = true; + actionState->frame = Time.frameCount; } else if (actionState->isPressed) { @@ -1587,6 +1590,7 @@ private void ProcessButtonState(ref TriggerState trigger, int actionIndex, Bindi { actionState->releasedInUpdate = InputUpdate.s_UpdateStepCount; actionState->isPressed = false; + actionState->frame = Time.frameCount; } } } @@ -2445,6 +2449,7 @@ private void ChangePhaseOfActionInternal(int actionIndex, TriggerState* actionSt newState.magnitude = 0f; newState.phase = newPhase; + newState.frame = Time.frameCount; if (newPhase == InputActionPhase.Performed) { newState.lastPerformedInUpdate = InputUpdate.s_UpdateStepCount; @@ -3627,7 +3632,7 @@ public int partIndex /// other is to represent the current actuation state of an action as a whole. The latter is stored in /// while the former is passed around as temporary instances on the stack. /// - [StructLayout(LayoutKind.Explicit, Size = 52)] + [StructLayout(LayoutKind.Explicit, Size = 56)] public struct TriggerState { public const int kMaxNumMaps = byte.MaxValue; @@ -3651,6 +3656,7 @@ public struct TriggerState [FieldOffset(40)] private uint m_PressedInUpdate; [FieldOffset(44)] private uint m_ReleasedInUpdate; [FieldOffset(48)] private uint m_LastCompletedInUpdate; + [FieldOffset(52)] private int m_Frame; /// /// Phase being triggered by the control value change. @@ -3806,6 +3812,12 @@ public uint lastPerformedInUpdate set => m_LastPerformedInUpdate = value; } + internal int frame + { + get => m_Frame; + set => m_Frame = value; + } + /// /// Update step count () in which action completed last. /// Zero if the action did not become completed yet. Also reset to zero when the action is hard reset.