Skip to content

Commit 176e46f

Browse files
authored
Add API additions to assist with polling workflow (#1795)
NEW: Adding new fields and methods InputAction.activeValueType, InputAction.GetMagnitude and InputAction.WasCompletedThisFrame
1 parent f625836 commit 176e46f

File tree

8 files changed

+1626
-58
lines changed

8 files changed

+1626
-58
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ docerrors.log
2828

2929
Assets/**/*.api
3030
Assets/**/*.api.meta
31+
Assets/__TestInputAsset.inputactions
32+
Assets/__TestInputAsset.inputactions.meta
3133

3234
Packages/packages-lock.json
3335
Packages/com.unity.inputsystem/artifacts/**

Assets/Tests/InputSystem/CoreTests_Actions.cs

Lines changed: 1384 additions & 17 deletions
Large diffs are not rendered by default.

Packages/com.unity.inputsystem/CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,14 @@ however, it has to be formatted properly to pass verification tests.
1313
### Changed
1414
- From 2023.2 forward: UI toolkit now uses the "UI" action map of project-wide actions as their default input actions. Previously, the actions were hardcoded and were based on `DefaultInputActions` asset which didn't allow user changes. Also, removing bindings or renaming the 'UI' action map of project wide actions will break UI input for UI toolkit.
1515

16+
### Added
17+
- Added new methods and properties to [`InputAction`](xref:UnityEngine.InputSystem.InputAction):
18+
- [`InputAction.activeValueType`](xref:UnityEngine.InputSystem.InputAction.activeValueType) returns the `Type` expected by `ReadValue<TValue>` based on the currently active control that is driving the action.
19+
- [`InputAction.GetMagnitude`](xref:UnityEngine.InputSystem.InputAction.GetMagnitude) returns the current amount of actuation of the control that is driving the action.
20+
- [`InputAction.WasCompletedThisFrame`](xref:UnityEngine.InputSystem.InputAction.WasCompletedThisFrame) returns `true` on the frame that the action stopped being in the performed phase. This allows for similar functionality to [`WasPressedThisFrame`](xref:UnityEngine.InputSystem.InputAction.WasPressedThisFrame)/[`WasReleasedThisFrame`](xref:UnityEngine.InputSystem.InputAction.WasReleasedThisFrame) when paired with [`WasPerformedThisFrame`](xref:UnityEngine.InputSystem.InputAction.WasPerformedThisFrame) except it is directly based on the interactions driving the action. For example, you can use it to distinguish between the button being released or whether it was released after being held for long enough to perform when using the Hold interaction.
21+
1622
### Fixed
23+
- Fixed syntax of code examples in API documentation for [`AxisComposite`](xref:UnityEngine.InputSystem.Composites.AxisComposite).
1724
- Fixed missing confirmation popup when deleting a control scheme.
1825
- Fixed support for menu bar/customisable keyboard shortcuts used when interacting with Actions and Action Maps.
1926
- Fixed add bindings button to support left button click.

Packages/com.unity.inputsystem/Documentation~/Interactions.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ An Interaction has a set of distinct phases it can go through in response to rec
3535
|`Waiting`|The Interaction is waiting for input.|
3636
|`Started`|The Interaction has been started (that is, it received some of its expected input), but is not complete yet.|
3737
|`Performed`|The Interaction is complete.|
38-
|`Canceled`|The Interaction was interrupted and aborted. For example, the user pressed and then released a button before the minimum time required for a [hold Interaction](#hold) to complete.|
38+
|`Canceled`|The Interaction was interrupted and aborted. For example, the user pressed and then released a button before the minimum time required for a [hold Interaction](#hold) to complete.|
3939

4040
Not every Interaction triggers every phase, and the pattern in which specific Interactions trigger phases depends on the Interaction type.
4141

@@ -163,7 +163,7 @@ If you haven't specifically added an Interaction to a Binding or its Action, the
163163

164164
|__Callback__|[`InputActionType.Value`](RespondingToActions.md#value)|[`InputActionType.Button`](RespondingToActions.md#button)|[`InputActionType.PassThrough`](RespondingToActions.md#pass-through)|
165165
|-----------|-------------|------------|-----------------|
166-
|[`started`](../api/UnityEngine.InputSystem.InputAction.html#UnityEngine_InputSystem_InputAction_started)|Control(s) changed value away from the default value.|Button started being pressed but has not necessarily crossed the press threshold yet.|First Control actuation after Action was enabled.|
166+
|[`started`](../api/UnityEngine.InputSystem.InputAction.html#UnityEngine_InputSystem_InputAction_started)|Control(s) changed value away from the default value.|Button started being pressed but has not necessarily crossed the press threshold yet.|not used|
167167
|[`performed`](../api/UnityEngine.InputSystem.InputAction.html#UnityEngine_InputSystem_InputAction_performed)|Control(s) changed value.|Button was pressed to at least the button [press threshold](../api/UnityEngine.InputSystem.InputSettings.html#UnityEngine_InputSystem_InputSettings_defaultButtonPressPoint).|Control changed value.|
168168
|[`canceled`](../api/UnityEngine.InputSystem.InputAction.html#UnityEngine_InputSystem_InputAction_canceled)|Control(s) are no longer actuated.|Button was released. If the button was pressed above the press threshold, the button has now fallen to or below the [release threshold](../api/UnityEngine.InputSystem.InputSettings.html#UnityEngine_InputSystem_InputSettings_buttonReleaseThreshold). If the button was never fully pressed, the button is now back to completely unpressed.|Action is disabled.|
169169

Packages/com.unity.inputsystem/Documentation~/RespondingToActions.md

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
There are two main techniques you can use to respond to Actions in your project. These are to either use **polling** or an **event-driven** approach.
55

6-
- The **Polling** approach refers to the technique of repeatedly checking the current state of the Actions you are interested in. Typically you would do this in the Update() method of a Monobehaviour script.
6+
- The **Polling** approach refers to the technique of repeatedly checking the current state of the Actions you are interested in. Typically you would do this in the `Update()` method of a `MonoBehaviour` script.
77
- The **Event-driven** approach involves creating your own methods in code that are automatically called when an action is performed.
88

99
For most common scenarios, especially action games where the user's input should have a continuous effect on an in-game character, **Polling** is usually simpler and easier to implement.
@@ -39,27 +39,40 @@ public class Example : MonoBehaviour
3939

4040
Note that the value type has to correspond to the value type of the control that the value is being read from.
4141

42-
To determine whether an action was performed in the current frame, you can use [`InputAction.WasPerformedThisFrame()`](../api/UnityEngine.InputSystem.InputAction.html#UnityEngine_InputSystem_InputAction_WasPerformedThisFrame):
42+
There are two methods you can use to poll for `performed` [action callbacks](#action-callbacks) to determine whether an action was performed or stopped performing in the current frame.
4343

44+
These methods differ from [`InputAction.WasPressedThisFrame()`](../api/UnityEngine.InputSystem.InputAction.html#UnityEngine_InputSystem_InputAction_WasPressedThisFrame) and [`InputAction.WasReleasedThisFrame()`](../api/UnityEngine.InputSystem.InputAction.html#UnityEngine_InputSystem_InputAction_WasReleasedThisFrame) in that these depend directly on the [Interactions](Interactions.md) driving the action (including the [default Interaction](Interactions.md#default-interaction) if no specific interaction has been added to the action or binding).
45+
46+
|Method|Description|
47+
|------|-----------|
48+
|[`InputAction.WasPerformedThisFrame()`](../api/UnityEngine.InputSystem.InputAction.html#UnityEngine_InputSystem_InputAction_WasPerformedThisFrame)|True if the [`InputAction.phase`](../api/UnityEngine.InputSystem.InputAction.html#UnityEngine_InputSystem_InputAction_phase) of the action has, at any point during the current frame, changed to [`Performed`](../api/UnityEngine.InputSystem.InputActionPhase.html#UnityEngine_InputSystem_InputActionPhase_Performed).|
49+
|[`InputAction.WasCompletedThisFrame()`](../api/UnityEngine.InputSystem.InputAction.html#UnityEngine_InputSystem_InputAction_WasCompletedThisFrame)|True if the [`InputAction.phase`](../api/UnityEngine.InputSystem.InputAction.html#UnityEngine_InputSystem_InputAction_phase) of the action has, at any point during the current frame, changed away from [`Performed`](../api/UnityEngine.InputSystem.InputActionPhase.html#UnityEngine_InputSystem_InputActionPhase_Performed) to any other phase. This can be useful for [Button](#button) actions or [Value](#value) actions with interactions like [Press](Interactions.md#press) or [Hold](Interactions.md#hold) when you want to know the frame the interaction stops being performed. For actions with the [default Interaction](Interactions.md#default-interaction), this method will always return false for [Value](#value) and [Pass-Through](#pass-through) actions (since the phase stays in [`Started`](../api/UnityEngine.InputSystem.InputActionPhase.html#UnityEngine_InputSystem_InputActionPhase_Started) for Value actions and stays in [`Performed`](../api/UnityEngine.InputSystem.InputActionPhase.html#UnityEngine_InputSystem_InputActionPhase_Performed) for Pass-Through).|
50+
51+
This example uses the Interact action from the [default actions](ActionsEditor.md#the-default-actions), which has a [Hold](Interactions.md#hold) interaction to make it perform only after the bound control is held for a period of time (for example, 0.4 seconds):
4452

4553
```CSharp
4654
using UnityEngine;
4755
using UnityEngine.InputSystem;
4856

4957
public class Example : MonoBehaviour
5058
{
51-
InputAction jumpAction;
59+
InputAction interactAction;
5260

5361
private void Start()
5462
{
55-
jumpAction = InputSystem.actions.FindAction("Jump");
63+
interactAction = InputSystem.actions.FindAction("Interact");
5664
}
5765

5866
void Update()
5967
{
60-
if (jumpAction.WasPerformedThisFrame())
68+
if (interactAction.WasPerformedThisFrame())
6169
{
62-
// your code to respond to the Jump action here
70+
// your code to respond to the first frame that the Interact action is held for enough time
71+
}
72+
73+
if (interactAction.WasCompletedThisFrame())
74+
{
75+
// your code to respond to the frame that the Interact action is released after being held for enough time
6376
}
6477
}
6578
}
@@ -73,7 +86,7 @@ Finally, there are three methods you can use to poll for button presses and rele
7386
|[`InputAction.WasPressedThisFrame()`](../api/UnityEngine.InputSystem.InputAction.html#UnityEngine_InputSystem_InputAction_WasPressedThisFrame)|True if the level of [actuation](../api/UnityEngine.InputSystem.InputControl.html#UnityEngine_InputSystem_InputControl_EvaluateMagnitude) on the action has, at any point during the current frame, reached or gone above the [press point](../api/UnityEngine.InputSystem.InputSettings.html#UnityEngine_InputSystem_InputSettings_defaultButtonPressPoint).|
7487
|[`InputAction.WasReleasedThisFrame()`](../api/UnityEngine.InputSystem.InputAction.html#UnityEngine_InputSystem_InputAction_WasReleasedThisFrame)|True if the level of [actuation](../api/UnityEngine.InputSystem.InputControl.html#UnityEngine_InputSystem_InputControl_EvaluateMagnitude) on the action has, at any point during the current frame, gone from being at or above the [press point](../api/UnityEngine.InputSystem.InputSettings.html#UnityEngine_InputSystem_InputSettings_defaultButtonPressPoint) to at or below the [release threshold](../api/UnityEngine.InputSystem.InputSettings.html#UnityEngine_InputSystem_InputSettings_buttonReleaseThreshold).|
7588

76-
This example uses three actions called Shield, Teleport and Submit (which are not included in the [default actions]()):
89+
This example uses three actions called Shield, Teleport and Submit (which are not included in the [default actions](ActionsEditor.md#the-default-actions)):
7790

7891
```CSharp
7992
using UnityEngine;
@@ -101,15 +114,13 @@ public class Example : MonoBehaviour
101114

102115
if (teleportAction.WasPressedThisFrame())
103116
{
104-
// teleport occurs on the first frame that the action was performed, and not again until the button is released
117+
// teleport occurs on the first frame that the action is pressed, and not again until the button is released
105118
}
106119

107120
if (submit.WasReleasedThisFrame())
108121
{
109122
// submit occurs on the frame that the action is released, a common technique for buttons relating to UI controls.
110123
}
111-
112-
113124
}
114125
}
115126
```

Packages/com.unity.inputsystem/InputSystem/Actions/Composites/AxisComposite.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ namespace UnityEngine.InputSystem.Composites
1616
/// <example>
1717
/// <code>
1818
/// var action = new InputAction();
19-
/// action.AddCompositeBinding("Axis(minValue=0,maxValue=2")
19+
/// action.AddCompositeBinding("Axis(minValue=0,maxValue=2)")
2020
/// .With("Negative", "&lt;Keyboard&gt;/a")
2121
/// .With("Positive", "&lt;Keyboard&gt;/d");
2222
/// </code>
@@ -73,7 +73,7 @@ public class AxisComposite : InputBindingComposite<float>
7373
/// <example>
7474
/// <code>
7575
/// var action = new InputAction();
76-
/// action.AddCompositeBinding("Axis(minValue=0,maxValue=2")
76+
/// action.AddCompositeBinding("Axis(minValue=0,maxValue=2)")
7777
/// .With("Negative", "&lt;Keyboard&gt;/a")
7878
/// .With("Positive", "&lt;Keyboard&gt;/d");
7979
/// </code>
@@ -95,7 +95,7 @@ public class AxisComposite : InputBindingComposite<float>
9595
/// <example>
9696
/// <code>
9797
/// var action = new InputAction();
98-
/// action.AddCompositeBinding("Axis(minValue=0,maxValue=2")
98+
/// action.AddCompositeBinding("Axis(minValue=0,maxValue=2)")
9999
/// .With("Negative", "&lt;Keyboard&gt;/a")
100100
/// .With("Positive", "&lt;Keyboard&gt;/d");
101101
/// </code>

0 commit comments

Comments
 (0)