test
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"timestamp": 1729075508,
|
||||
"signature": "AEOT4U6FsbZYEXDtlnA5Te+cWeF/ImeLpiP8PAKuwnzqd17UxQ0KdiDMg+aLixfz45G1B+yb8Zf5f+v7HxGvMEX6Ci1YPcaFNOIrLdqtWxOsx+ujsMjTGU591xM8TLQIxHxfhCFxYY+8sfjNCSMwXYXGa4CFBXcwYBeoHT9RntyBCCMN875zTKCeTUD5rEwF5XFrHjcDsbFSDnH1RXvabzfzZDZrZJ3jq2KrYltTQQFcwxrlwXI5iMl8fzHh2/M4I9tR8OOiBjFSjvJZqRc89VkoGlInxqh2v9EEcSsI5P/CeabSCFNiOIQcyb9ofO6TDeV3UWy9Vk0Bc1ztiN74j42r95g9ouwLWsbF++RDqm0cJituaZwdkAfrrHAsuaXOCfb4TIj1A1oUNKUicGckiT/LS0iT3QWGCj17I9ZZX27EUa7j5eAsqazcs+IDV1idRtTk5lYtlVIwmjgAM9pCpn+egMdpQxxtuRFwSgiRX3Ra938Ka4pgoTHwBYDTvbEu",
|
||||
"publicKey": "LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUlJQm9qQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FZOEFNSUlCaWdLQ0FZRUFzdUhXYUhsZ0I1cVF4ZEJjTlJKSAordHR4SmoxcVY1NTdvMlZaRE1XaXhYRVBkRTBEMVFkT1JIRXNSS1RscmplUXlERU83ZlNQS0ZwZ1A3MU5TTnJCCkFHM2NFSU45aHNQVDhOVmllZmdWem5QTkVMenFkVmdEbFhpb2VpUnV6OERKWFgvblpmU1JWKytwbk9ySTRibG4KS0twelJlNW14OTc1SjhxZ1FvRktKT0NNRlpHdkJMR2MxSzZZaEIzOHJFODZCZzgzbUovWjBEYkVmQjBxZm13cgo2ZDVFUXFsd0E5Y3JZT1YyV1VpWXprSnBLNmJZNzRZNmM1TmpBcEFKeGNiaTFOaDlRVEhUcU44N0ZtMDF0R1ZwCjVNd1pXSWZuYVRUemEvTGZLelR5U0pka0tldEZMVGdkYXpMYlpzUEE2aHBSK0FJRTJhc0tLTi84UUk1N3UzU2cKL2xyMnZKS1IvU2l5eEN1Q20vQWJkYnJMbXk0WjlSdm1jMGdpclA4T0lLQWxBRWZ2TzV5Z2hSKy8vd1RpTFlzUQp1SllDM0V2UE16ZGdKUzdGR2FscnFLZzlPTCsxVzROY05yNWdveVdSUUJ0cktKaWlTZEJVWmVxb0RvSUY5NHpCCndGbzJJT1JFdXFqcU51M3diMWZIM3p1dGdtalFra3IxVjJhd3hmcExLWlROQWdNQkFBRT0KLS0tLS1FTkQgUFVCTElDIEtFWS0tLS0tCg"
|
||||
}
|
2184
My project/Library/PackageCache/com.unity.inputsystem/CHANGELOG.md
Normal file
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a3e12f7b92d6e49c0b430ae7813c2398
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
5
My project/Library/PackageCache/com.unity.inputsystem/Documentation~/.vscode/spellright.dict
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
inputactions
|
||||
playerinput
|
||||
inputsystemuiinputmodule
|
||||
gravitysensor
|
||||
deadzone
|
@@ -0,0 +1,120 @@
|
||||
---
|
||||
uid: input-system-action-assets
|
||||
---
|
||||
# Input Action Assets
|
||||
|
||||
- [Creating Input Action Assets](#creating-input-action-assets)
|
||||
- [Editing Input Action Assets](#editing-input-action-assets)
|
||||
- [Using Input Action Assets](#using-input-action-assets)
|
||||
- [Type-safe C# API Generation](#type-safe-c-api-generation)
|
||||
|
||||
An Input Action Asset is an Asset which contains a set of [Input Actions](Actions.md) definitions and their associated [Bindings](ActionBindings.md) and [Control Schemes](ActionBindings.md#control-schemes). These Assets have the `.inputactions` file extension and are stored in a plain JSON format.
|
||||
|
||||
The input system creates an Action Asset when you set up the [default project-wide actions](ProjectWideActions.md), but you can also create new Action Assets directly in the Project window.
|
||||
|
||||
For most common scenarios, you do not need to use more than one Input Action Asset. It is usually simpler to configure your project-wide action definition in the Project Settings window.
|
||||
|
||||
|
||||
## Creating Input Action Assets
|
||||
|
||||
To create an Asset that contains [Input Actions](Actions.md) in Unity, right-click in the __Project__ window or go to __Assets > Create > Input Actions__ from Unity's main menu.
|
||||
|
||||
## Editing Input Action Assets
|
||||
|
||||
To bring up the Action editor, double-click an `.inputactions` Asset in the Project Browser, or select the __Edit Asset__ button in the Inspector for that Asset. You can have more than one editor window open at the same time, but not for the same Asset.
|
||||
|
||||
The Actions Editor which opens is identical to the [Actions Editor in the Project Settings window](ActionsEditor.md).
|
||||
|
||||
|
||||
## Using Input Action Assets
|
||||
|
||||
|
||||
## Type-safe C# API Generation
|
||||
|
||||
Input Action Assets allow you to **generate a C# class** from your action definitions, which allow you to refer to your actions in a type-safe manner from code. This means you can avoid looking up your actions by string.
|
||||
|
||||
### Auto-generating script code for Actions
|
||||
|
||||
One of the most convenient ways to work with `.inputactions` Assets in scripts is to automatically generate a C# wrapper class for them. This removes the need to manually look up Actions and Action Maps using their names, and also provides an easier way to set up callbacks.
|
||||
|
||||
To enable this option, tick the __Generate C# Class__ checkbox in the importer properties in the Inspector of the `.inputactions` Asset, then select __Apply__.
|
||||
|
||||

|
||||
|
||||
You can optionally choose a path name, class name, and namespace for the generated script, or keep the default values.
|
||||
|
||||
This generates a C# script that simplifies working with the Asset.
|
||||
|
||||
```CSharp
|
||||
using UnityEngine;
|
||||
using UnityEngine.InputSystem;
|
||||
|
||||
// IGameplayActions is an interface generated from the "gameplay" action map
|
||||
// we added (note that if you called the action map differently, the name of
|
||||
// the interface will be different). This was triggered by the "Generate Interfaces"
|
||||
// checkbox.
|
||||
public class MyPlayerScript : MonoBehaviour, IGameplayActions
|
||||
{
|
||||
// MyPlayerControls is the C# class that Unity generated.
|
||||
// It encapsulates the data from the .inputactions asset we created
|
||||
// and automatically looks up all the maps and actions for us.
|
||||
MyPlayerControls controls;
|
||||
|
||||
public void OnEnable()
|
||||
{
|
||||
if (controls == null)
|
||||
{
|
||||
controls = new MyPlayerControls();
|
||||
// Tell the "gameplay" action map that we want to get told about
|
||||
// when actions get triggered.
|
||||
controls.gameplay.SetCallbacks(this);
|
||||
}
|
||||
controls.gameplay.Enable();
|
||||
}
|
||||
|
||||
public void OnDisable()
|
||||
{
|
||||
controls.gameplay.Disable();
|
||||
}
|
||||
|
||||
public void OnUse(InputAction.CallbackContext context)
|
||||
{
|
||||
// 'Use' code here.
|
||||
}
|
||||
|
||||
public void OnMove(InputAction.CallbackContext context)
|
||||
{
|
||||
// 'Move' code here.
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
>__Note__: To regenerate the .cs file, right-click the .inputactions asset in the Project Browser and choose "Reimport".
|
||||
|
||||
### Using Action Assets with `PlayerInput`
|
||||
|
||||
The [Player Input](PlayerInput.md) component provides a convenient way to handle input for one or multiple players. You can assign your Action Asset to the Player Input component so that it can then automatically handle activating Action Maps and selecting Control Schemes for you.
|
||||
|
||||

|
||||
|
||||
### Modifying Input Action Assets at runtime
|
||||
There are several ways to modify an Input Action Asset at runtime. Any modifications that you make during Play mode to an Input Action Asset do not persist in the Input Action Asset after you exit Play mode. This means you can test your application in a realistic manner in the Editor without having to worry about inadvertently modifying the asset. For examples on how to modify an Input Action Asset, see the documentation on [Creating Actions in code](Actions.md#creating-actions-in-code) and [Changing Bindings](ActionBindings.md#changing-bindings).
|
||||
|
||||
|
||||
### The Default Actions Asset
|
||||
|
||||
An asset called `DefaultInputActions.inputactions` containing a default setup of Actions comes with the Input System Package. You can reference this asset directly in your projects like any other Unity asset. However, the asset is also available in code form through the [`DefaultInputActions`](../api/UnityEngine.InputSystem.DefaultInputActions.html) class.
|
||||
|
||||
```CSharp
|
||||
void Start()
|
||||
{
|
||||
// Create an instance of the default actions.
|
||||
var actions = new DefaultInputActions();
|
||||
actions.Player.Look.performed += OnLook;
|
||||
actions.Player.Move.performed += OnMove;
|
||||
actions.Enable();
|
||||
}
|
||||
```
|
||||
|
||||
> __Note:__ This default actions asset is older than, and entirely separate from the [default project-wide actions](ProjectWideActions.md). It is a legacy asset that remains included in the package for backward compatibility.
|
@@ -0,0 +1,158 @@
|
||||
---
|
||||
uid: input-system-actions
|
||||
---
|
||||
# Actions
|
||||
|
||||
**Actions** are an important concept in the Input System. They allow you to separate the purpose of an input from the device controls which perform that input. Actions allow you to associate the purpose and device controls together in a flexible way.
|
||||
|
||||
For example, the purpose of an input in a game might be to make the player's character move around. The device control associated with that action might be the motion of the left gamepad stick.
|
||||
|
||||
The association between an Action and the device controls which perform that input is a **binding**, and you can set up bindings in the [Input Actions editor](ActionsEditor.md). When you use Actions in your code, you do not need to refer to specific devices because the binding defines which device's controls are used to perform the action.
|
||||
|
||||
To use actions in your code, you must use the [Input Actions editor](ActionsEditor.md) to establish the mapping between the Action and one or more device controls. For example in this screenshot, the "Move" action is displayed, showing its bindings the left gamepad stick, and the keyboard's arrow keys.
|
||||
|
||||
<br/>
|
||||
*The Actions panel of the Input Actions Editor in Project Settings*
|
||||
|
||||
You can then get a reference to this action in your code, and check its value, or attach a callback method to be notified when it is performed. See the [Actions Workflow page](Workflow-Actions.md) for a simple example script demonstrating this.
|
||||
|
||||
Actions also make it simpler to create a system that lets your players [customize their bindings at runtime](ActionBindings.md#interactive-rebinding), which is a common requirement for games.
|
||||
|
||||
>**Notes:**
|
||||
> - Actions are a runtime only feature. You can't use them in [Editor window code](https://docs.unity3d.com/ScriptReference/EditorWindow.html).
|
||||
>
|
||||
> - You can read input without using Actions and Bindings by directly reading specific device controls. This is less flexible, but can be quicker to implement for certain situations. Read more about [directly reading devices from script](Workflow-Direct.md).
|
||||
>
|
||||
> - Although you can reorder actions in this window, the ordering is for visual convenience only, and does not affect the order in which the actions are triggered in your code. If multiple actions are performed in the same frame, the order in which they are reported by the input system is undefined. To avoid problems, you should not write code that assumes they will be reported in a particular order.
|
||||
> <br/>
|
||||
|
||||
|
||||
## Overview
|
||||
|
||||
When scripting with Actions in the Input System, there are number of important API you can use, which are described here:
|
||||
|
||||
|API name|Description|
|
||||
|-----|-----------|
|
||||
|[`InputSystem.actions`](../api/UnityEngine.InputSystem.InputSystem.html)|A reference to the set of actions assigned as the [project-wide Actions](./ProjectWideActions.md).|
|
||||
|[`InputActionMap`](../api/UnityEngine.InputSystem.InputActionMap.html)|A named collection of Actions. The API equivalent to an entry in the "Action Maps" column of the [Input Actions editor](ActionsEditor.md).|
|
||||
|[`InputAction`](../api/UnityEngine.InputSystem.InputAction.html)|A named Action that can return the current value of the controls that it is bound to, or can trigger callbacks in response to input. The API equivalent to an entry in the "Actions" column of the [Input Actions editor](ActionsEditor.md).|
|
||||
|[`InputBinding`](../api/UnityEngine.InputSystem.InputBinding.html)|The relationship between an Action and the specific device controls for which it receives input. For more information about Bindings and how to use them, see [Action Bindings](ActionBindings.md).|
|
||||
|
||||
Each Action has a name ([`InputAction.name`](../api/UnityEngine.InputSystem.InputAction.html#UnityEngine_InputSystem_InputAction_name)), which must be unique within the Action Map that the Action belongs to, if any (see [`InputAction.actionMap`](../api/UnityEngine.InputSystem.InputAction.html#UnityEngine_InputSystem_InputAction_actionMap)). Each Action also has a unique ID ([`InputAction.id`](../api/UnityEngine.InputSystem.InputAction.html#UnityEngine_InputSystem_InputAction_id)), which you can use to reference the Action. The ID remains the same even if you rename the Action.
|
||||
|
||||
Each Action Map has a name ([`InputActionMap.name`](../api/UnityEngine.InputSystem.InputActionMap.html#UnityEngine_InputSystem_InputActionMap_name)), which must also be unique with respect to the other Action Maps present, if any. Each Action Map also has a unique ID ([`InputActionMap.id`](../api/UnityEngine.InputSystem.InputActionMap.html#UnityEngine_InputSystem_InputActionMap_id)), which you can use to reference the Action Map. The ID remains the same even if you rename the Action Map.
|
||||
|
||||
## Creating Actions
|
||||
|
||||
The simplest way to create actions is to use the [Input Actions editor](ActionsEditor.md) in the Project Settings window. This is the primary recommended workflow and suitable for most scenarios.
|
||||
|
||||
However, because the input system API is very open, there are many other ways to create actions which may suit less common scenarios. For example, by loading actions from JSON data, or creating actions entirely in code.
|
||||
|
||||
### Creating Actions using the Action editor
|
||||
|
||||
For information on how to create and edit Input Actions in the editor, see the [Input Actions editor](ActionsEditor.md). This is the recommended workflow if you want to organise all your input actions and bindings in one place, which applies across the whole of your project. This often the case for most types of game or app.
|
||||
|
||||

|
||||
*The Input Actions Editor in the Project Settings window*
|
||||
|
||||
|
||||
# Other ways to create Actions
|
||||
|
||||
The simplest way to create actions is to use the [Input Actions editor](ActionsEditor.md) to configure a set of actions in an asset, as described above. However, because the Input System package API is open and flexible, you can create actions using alternative techniques. These alternatives might be more suitable if you want to customize your project beyond the standard workflow.
|
||||
|
||||
### Creating Actions by declaring them in MonoBehaviours
|
||||
|
||||
As an alternative workflow, you can declare individual [Input Action](../api/UnityEngine.InputSystem.InputAction.html) and [Input Action Maps](../api/UnityEngine.InputSystem.InputActionMap.html) as fields directly inside `MonoBehaviour` components.
|
||||
|
||||
```CSharp
|
||||
using UnityEngine;
|
||||
using UnityEngine.InputSystem;
|
||||
|
||||
public class ExampleScript : MonoBehaviour
|
||||
{
|
||||
public InputAction move;
|
||||
public InputAction jump;
|
||||
}
|
||||
```
|
||||
|
||||
The result is similar to using an Actions defined in the Input Actions editor, except the Actions are defined in the GameObject's properties and saved as Scene or Prefab data, instead of in a dedicated Asset.
|
||||
|
||||
When you embed actions like this, by defining serialized InputAction fields in a MonoBehaviour, the GameObject's Inspector window displays an interface similar to the Actions column of the [Actions Editor](./ActionsEditor.md), which allows you to set up the bindings for those actions. For example:
|
||||
|
||||

|
||||
|
||||
* To add or remove Actions or Bindings, click the Add (+) or Remove (-) icon in the header.
|
||||
* To edit Bindings, double-click them.<br>
|
||||
* To edit Actions, double-click them in an Action Map, or click the gear icon on individual Action properties.<br>
|
||||
* You can also right-click entries to bring up a context menu, and you can drag them. Hold the Alt key and drag an entry to duplicate it.
|
||||
|
||||
Unlike the project-wide actions in the Project Settings window, you must manually enable and disable Actions and Action Maps that are embedded in MonoBehaviour components.
|
||||
|
||||
When you use this workflow, the serialised action configurations are stored with the parent GameObject as part of the scene, opposite to being serialised with an Action Asset. This can be useful if you want to bundle the control bindings and behaviour together in a single monobehaviour or prefab, so it can be distributed together. However, this can also make it harder to organize your full set of control bindings if they are distributed across multiple prefabs or scenes.
|
||||
|
||||
### Loading Actions from JSON
|
||||
|
||||
You can load Actions as JSON in the form of a set of Action Maps or as a full [`InputActionAsset`](../api/UnityEngine.InputSystem.InputActionAsset.html). This also works at runtime in the Player.
|
||||
|
||||
```CSharp
|
||||
// Load a set of action maps from JSON.
|
||||
var maps = InputActionMap.FromJson(json);
|
||||
|
||||
// Load an entire InputActionAsset from JSON.
|
||||
var asset = InputActionAsset.FromJson(json);
|
||||
```
|
||||
|
||||
### Creating Actions in code
|
||||
|
||||
You can manually create and configure Actions entirely in code, including assigning the bindings. This also works at runtime in the Player. For example:
|
||||
|
||||
```CSharp
|
||||
// Create free-standing Actions.
|
||||
var lookAction = new InputAction("look", binding: "<Gamepad>/leftStick");
|
||||
var moveAction = new InputAction("move", binding: "<Gamepad>/rightStick");
|
||||
|
||||
lookAction.AddBinding("<Mouse>/delta");
|
||||
moveAction.AddCompositeBinding("Dpad")
|
||||
.With("Up", "<Keyboard>/w")
|
||||
.With("Down", "<Keyboard>/s")
|
||||
.With("Left", "<Keyboard>/a")
|
||||
.With("Right", "<Keyboard>/d");
|
||||
|
||||
// Create an Action Map with Actions.
|
||||
var map = new InputActionMap("Gameplay");
|
||||
var lookAction = map.AddAction("look");
|
||||
lookAction.AddBinding("<Gamepad>/leftStick");
|
||||
|
||||
// Create an Action Asset.
|
||||
var asset = ScriptableObject.CreateInstance<InputActionAsset>();
|
||||
var gameplayMap = new InputActionMap("gameplay");
|
||||
asset.AddActionMap(gameplayMap);
|
||||
var lookAction = gameplayMap.AddAction("look", "<Gamepad>/leftStick");
|
||||
```
|
||||
|
||||
Any action that you create in this way during Play mode do not persist in the Input Action Asset after you exit Play mode. This means you can test your application in a realistic manner in the Editor without having to worry about inadvertently modifying the asset.
|
||||
|
||||
|
||||
## Enabling actions
|
||||
|
||||
Actions have an **enabled** state, meaning you can enable or disable them to suit different situations.
|
||||
|
||||
If you have an Action Asset assigned as [project-wide](./ProjectWideActions.md), the actions it contains are enabled by default and ready to use.
|
||||
|
||||
For actions defined elsewhere, such as in an Action Asset not assigned as project-wide, or defined your own code, they begin in a disabled state, and you must enable them before they will respond to input.
|
||||
|
||||
You can enable actions individually, or as a group by enabling the Action Map which contains them.
|
||||
|
||||
```CSharp
|
||||
// Enable a single action.
|
||||
lookAction.Enable();
|
||||
|
||||
// Enable an en entire action map.
|
||||
gameplayActions.Enable();
|
||||
```
|
||||
|
||||
When you enable an Action, the Input System resolves its bindings, unless it has done so already, or if the set of devices that the Action can use has not changed. For more details about this process, see the documentation on [binding resolution](ActionBindings.md#binding-resolution).
|
||||
|
||||
You can't change certain aspects of the configuration, such Action Bindings, while an Action is enabled. To stop Actions or Action Maps from responding to input, call [`Disable`](../api/UnityEngine.InputSystem.InputAction.html#UnityEngine_InputSystem_InputAction_Disable).
|
||||
|
||||
While enabled, an Action actively monitors the [Control(s)](Controls.md) it's bound to. If a bound Control changes state, the Action processes the change. If the Control's change represents an [Interaction](Interactions.md) change, the Action creates a response. All of this happens during the Input System update logic. Depending on the [update mode](Settings.md#update-mode) selected in the input settings, this happens once every frame, once every fixed update, or manually if updates are set to manual.
|
@@ -0,0 +1,142 @@
|
||||
---
|
||||
uid: input-system-configuring-input
|
||||
---
|
||||
# Configuring Input with the Actions Editor
|
||||
|
||||
The **Input Actions Editor** allows you to edit [Action Assets](ActionAssets.md), which contain a saved configuration of [Input Actions](Actions.md) and their associated [Bindings](ActionBindings.md).
|
||||
|
||||
It allows you to group collections of Actions into [Action Maps](ActionsEditor.html#configure-action-maps), which represent different input scenarios in your project (such as UI navigation, gameplay, etc.)
|
||||
|
||||
It also alows you to define [Control Schemes](ActionBindings.md#control-schemes) which are a way to enable or disable a set of devices, or respond to which type of device is being used. This is often useful if you want to customise your UI based on whether your users are using mouse, keyboard, or gamepad as their chosen input.
|
||||
|
||||
### Action Assets and Project-Wide Actions
|
||||
|
||||
The typical workflow for most projects is to have a single Action Asset, which is assigned as the **project-wide actions**. If you have not yet created and assigned an Actions Asset as the project-wide actions, the recommended workflow is to do this first. Read more about [project-wide actions](ProjectWideActions.md).
|
||||
|
||||
### Opening the Actions Editor
|
||||
|
||||
The **Input Actions Editor** is an editor window displayed when you open an Action Asset by double-clicking it.
|
||||
|
||||
It is also displayed in the Project Settings window under **Edit** > **Project Settings** > **Input System Package** if you have an Action Asset assigned as project-wide.
|
||||
|
||||

|
||||
*The Input Actions editor, displaying the default actions*
|
||||
|
||||
### The Actions Editor panels
|
||||
|
||||
The Input Actions editor is divided into three panels (marked A, B & C above).
|
||||
|
||||
|Name|Description|
|
||||
|-|-|
|
||||
|**(A) Action Maps**|Displays the list of currently defined Action Maps. Each Action Map is a collection of Actions that you can enable or disable together as a group.|
|
||||
|**(B) Actions**|Displays all the actions defined in the currently selected Action Map, and the bindings associated with each Action.|
|
||||
|**(C) Properties**|Displays the properties of the currently selected Action or Binding from the Actions panel. The title of this panel changes depending on whether you have an Action or a Binding selected in the Actions panel.|
|
||||
|
||||
### Configure Action Maps
|
||||
|
||||
* To add a new Action Map, select the Add (+) icon in the header of the Action Map panel.
|
||||
* To rename an existing Action Map, either long-click the name, or right-click the Action Map and select __Rename__ from the context menu. Note that Action Map names can't contain slashes (`/`).
|
||||
* To delete an existing Action Map, right-click it and select __Delete__ from the context menu.
|
||||
* To duplicate an existing Action Map, right-click it and select __Duplicate__ from the context menu.
|
||||
|
||||
### Configure Actions
|
||||
|
||||
* To add a new Action, select the Add (+) icon in the header of the Action column.
|
||||
* To rename an existing Action, either long-click the name, or right-click the Action Map and select __Rename__ from the context menu.
|
||||
* To delete an existing Action, either right-click it and select __Delete__ from the context menu.
|
||||
* To duplicate an existing Action, either right-click it and select __Duplicate__ from the context menu.
|
||||
*
|
||||
|
||||
|
||||
## Action type and Control type
|
||||
|
||||
If you select an Action, you can edit its properties in the right-hand pane of the window:
|
||||
|
||||

|
||||
|
||||
#### Action Type
|
||||
|
||||
The Action Type setting allows to to select between **Button**, **Value** or **PassThrough**.
|
||||
|
||||
These options relate to whether this action should represent a discrete on/off button-style interaction or a value that can change over time while the control is being used.
|
||||
|
||||
For device controls such as keyboard keys, mouse clicks, or gamepad buttons, select **Button**. For device controls such as mouse movement, a joystick or gamepad stick, or device orientation that provide continuously changing input over a period of time, select **Value**.
|
||||
|
||||
The Button and Value types of action also provides data about the action such as whether it has started and stopped, and conflict resolution in situations where multiple bindings are mapped to the same action.
|
||||
|
||||
The third option, **PassThrough**, is also a value type, and as such is suitable for the same types of device controls as value. The difference is that actions set to PassThrough only provide basic information about the values incoming from the device controls bound to it, and does not provide the extra data relating to the phase of the action, nor does it perform conflict resolution in the case of multiple controls mapped to the same action.
|
||||
|
||||
For more detail about how these types work, see [action types](RespondingToActions.html#action-types) and [default interactions](Interactions.html#default-interaction).
|
||||
|
||||
#### Control Type
|
||||
|
||||
The Control Type setting allows you to select the type of control expected by the action. This limits the controls shown when setting up bindings in the UI and also limits which contols can be bound interactively to the action.
|
||||
|
||||
For example, if you select **2D axis**, only those controls that can supply a 2D vector as value are available as options for the binding control path.
|
||||
|
||||
There are more specific control types available which futher filter the available bindings, such as "Stick", "Dpad" or "Touch". If you select one of these control types, the list of available controls is further limited to only those controls of those specific types when you select a binding for your action (see directly below).
|
||||
|
||||
### Bindings
|
||||
|
||||
* To add a new Binding, select the Add (+) icon on the action you want to add it to, and select the binding type from the menu that appears.
|
||||
* To delete an existing Binding, either right-click it and select __Delete__ from the context menu.
|
||||
* To duplicate an existing Binding, either right-click it and select __Duplicate__ from the context menu.
|
||||
|
||||
You can add multiple bindings to an action, which is generally useful for supporting multiple types of input device. For example, in the default set of actions, the "Move" action has a binding to the left gamepad stick and the WSAD keys, which means input through any of these bindings will perform the action.
|
||||
|
||||
<br/>
|
||||
_The default "Move" action in the Actions Editor window, displaying the multiple bindings associated with it._
|
||||
|
||||
If you select a Binding, you can edit its properties in the right-hand pane of the window:
|
||||
|
||||

|
||||
|
||||
#### Picking Controls
|
||||
|
||||
The most important property of any Binding is the [control path](Controls.md#control-paths) it's bound to. To edit it, open the __Path__ drop-down list. This displays a Control picker window.
|
||||
|
||||

|
||||
|
||||
In the Control picker window, you can explore a tree of Input Devices and Controls that the Input System recognizes, and bind to these Controls. Unity filters this list by the Action's [`Control Type`](../api/UnityEngine.InputSystem.InputAction.html#UnityEngine_InputSystem_InputAction_expectedControlType) property. For example, if the Control type is `Vector2`, you can only select a Control that generates two-dimensional values, like a stick.
|
||||
|
||||
The Device and Control tree is organized hierarchically from generic to specific. For example, the __Gamepad__ Control path `<Gamepad>/buttonSouth` matches the lower action button on any gamepad. Alternatively, if you navigate to __Gamepad__ > __More Specific Gamepads__ and select __PS4 Controller__, and then choose the Control path `<DualShockGamepad>/buttonSouth`, this only matches the "Cross" button on PlayStation gamepads, and doesn't match any other gamepads.
|
||||
|
||||
Instead of browsing the tree to find the Control you want, it's easier to let the Input System listen for input. To do that, select the __Listen__ button. At first, the list of Controls is empty. Once you start pressing buttons or actuating Controls on the Devices you want to bind to, the Control picker window starts listing any Bindings that match the controls you pressed. Select any of these Bindings to view them.
|
||||
|
||||
Finally, you can choose to manually edit the Binding path, instead of using the Control picker. To do that, select the __T__ button next to the Control path popup. This changes the popup to a text field, where you can enter any Binding string. This also allows you to use wildcard (`*`) characters in your Bindings. For example, you can use a Binding path such as `<Touchscreen>/touch*/press` to bind to any finger being pressed on the touchscreen, instead of manually binding to `<Touchscreen>/touch0/press`, `<Touchscreen>/touch1/press` and so on.
|
||||
|
||||
#### Editing Composite Bindings
|
||||
|
||||
Composite Bindings are Bindings consisting of multiple parts, which form a Control together. For instance, a [2D Vector Composite](ActionBindings.md#2d-vector) uses four buttons (left, right, up, down) to simulate a 2D stick input. See the [Composite Bindings](ActionBindings.md#composite-bindings) documentation to learn more.
|
||||
|
||||

|
||||
|
||||
To create a Composite Binding, in the Input Action Asset editor window, select the Add (+) icon on the Action you want to add it to, and select the Composite Binding type from the popup menu.
|
||||
|
||||

|
||||
|
||||
This creates multiple Binding entries for the Action: one for the Composite as a whole, and then, one level below that, one for each Composite part. The Composite itself doesn't have a Binding path property, but its individual parts do, and you can edit these parts like any other Binding. Once you bind all the Composite's parts, the Composite can work together as if you bound a single control to the Action.
|
||||
|
||||
**Note**: The set of Composites displayed in the menu is depends on the value type of the Action. This means that, for example, if the Action is set to type "Button", then only Composites able to return values of type `float` will be shown.
|
||||
|
||||
To change the type of a Composite retroactively, select the Composite, then select the new type from the **Composite Type** drop-down in the **Properties** pane.
|
||||
|
||||

|
||||
|
||||
To change the part of the Composite to which a particular Binding is assigned, use the **Composite Part** drop-down in the Binding's properties.
|
||||
|
||||

|
||||
|
||||
You can assign multiple Bindings to the same part. You can also duplicate individual part Bindings: right-click the Binding, then select **Duplicate** to create new part Bindings for the Composite. This can be used, for example, to create a single Composite for both "WASD" style controls and arrow keys.
|
||||
|
||||

|
||||
|
||||
### Editing Control Schemes
|
||||
|
||||
Input Action Assets can have multiple [Control Schemes](ActionBindings.md#control-schemes), which let you enable or disable different sets of Bindings for your Actions for different types of Devices.
|
||||
|
||||

|
||||
|
||||
To see the Control Schemes in the Input Action Asset editor window, open the Control Scheme drop-down list in the top left of the window. This menu lets you add or remove Control Schemes to your Actions Asset. If the Actions Asset contains any Control Schemes, you can select a Control Scheme, and then the window only shows bindings that are associated with that Scheme. If you select a binding, you can now pick the Control Schemes for which this binding should be active in the __Properties__ view to the left of the window.
|
||||
|
||||
When you add a new Control Scheme, or select an existing Control Scheme, and then select __Edit Control Scheme__, you can edit the name of the Control Scheme and which devices the Scheme should be active for. When you add a new Control Scheme, the "Device Type" list is empty by default (as shown above). You must add at least one type of device to this list for the Control Scheme to be functional.
|
@@ -0,0 +1,34 @@
|
||||
---
|
||||
uid: input-system-architecture
|
||||
---
|
||||
# Architecture
|
||||
|
||||
The Input System has a layered architecture that consists of a low-level layer and a high-level layer.
|
||||
|
||||
# Native backend
|
||||
|
||||
The foundation of the Input System is the native backend code. This is platform-specific code which collects information about available Devices and input data from Devices. This code is not part of the Input System package, but is included with Unity itself. It has implementations for each runtime platform supported by Unity. This is why some platform-specific input bugs can only be fixed by an update to Unity, rather than a new version of the Input System package.
|
||||
|
||||
The Input System interfaces with the native backend using [events](Events.md) that the native backend sends. These events notify the system of the creation and removal of [Input Devices](Devices.md), as well as any updates to the Device states. For efficiency and to avoid creating any garbage, the native backend reports these events as a simple buffer of raw, unmanaged memory containing a stream of events.
|
||||
|
||||
The Input System can also send data back to the native backend in the form of [commands](Devices.md#device-commands) sent to Devices, which are also buffers of memory that the native backend interprets. These commands can have different meanings for different Device types and platforms.
|
||||
|
||||
# Input System (low-level)
|
||||
|
||||

|
||||
|
||||
The low-level Input System code processes and interprets the memory from the event stream that the native backend provides, and dispatches individual events.
|
||||
|
||||
The Input System creates Device representations for any newly discovered Device in the event stream. The low-level code sees a Device as a block of raw, unmanaged memory. If it receives a state event for a Device, it writes the data from the state event into the Device's [state representation](Controls.md#control-state) in memory, so that the state always contains an up-to-date representation of the Device and all its Controls.
|
||||
|
||||
The low-level system code also contains structs which describe the data layout of commonly known Devices.
|
||||
|
||||
# Input System (high-level)
|
||||
|
||||

|
||||
|
||||
The high-level Input System code interprets the data in a Device's state buffers by using [layouts](Layouts.md), which describe the data layout of a Device and its Controls in memory. The Input System creates layouts from either the pre-defined structs of commonly known Devices supplied by the low level system, or dynamically at runtime, as in the case of [generic HIDs](HID.md#auto-generated-layouts).
|
||||
|
||||
Based on the information in the layouts, the Input System then creates [Control](Controls.md) representations for each of the Device's controls, which let you read the state of each individual Control in a Device.
|
||||
|
||||
As part of the high-level system, you can also build another abstraction layer to map Input Controls to your application mechanics. Use [Actions](Actions.md) to [bind](ActionBindings.md) one or more Controls to an input in your application. The Input System then monitors these Controls for state changes, and notifies your game logic using [callbacks](RespondingToActions.md#responding-to-actions-using-callbacks). You can also specify more complex behaviors for your Actions using [Processors](Processors.md) (which perform processing on the input data before sending it to you) and [Interactions](Interactions.md) (which let you specify patterns of input on a Control to listen to, such as multi-taps).
|
@@ -0,0 +1,19 @@
|
||||
---
|
||||
uid: basic-concepts
|
||||
---
|
||||
# Basic Concepts
|
||||
|
||||
This page introduces the basic concepts that relate to working with the Input System. They relate to the steps in the sequence of events that occur when a user sends input to your game or app. The Input System provides features which implement these steps, or you can choose to implement some of them yourself.
|
||||
|
||||

|
||||
|
||||
|Concept|Description|
|
||||
|-------|-----------|
|
||||
|[**User**](UserManagement.html)| The person playing your game or using your app, by holding or touching the input device and providing input.|
|
||||
|[**Input Device**](SupportedDevices.html)| Often referred to just as a "**device**" within the context of input. A physical piece of hardware, such as a keyboard, gamepad, mouse, or touchscreen which allows the user to send input into Unity.|
|
||||
|[**Control**](Controls.html)|The separate individual parts of an input device which each send input values into Unity. For example, a gamepad’s **controls** comprise multiple buttons, sticks and triggers, and a mouse’s controls include the two X and Y sensors on the underside, and the various buttons and scroll wheels on the top side.|
|
||||
|[**Action**](Actions.html)| Actions are a high-level concept that describe individual things that a user might want to do in your game or app, such as "Jump" within a game, or "Select" in an on-screen UI. They are things a user can do in your game or app as a result of input, regardless of what device or control they use to perform it. Actions generally have conceptual names that you choose to suit your project, and should usually be verbs. For example "Run", "Jump" "Crouch", "Use", "Start", "Quit".|
|
||||
|[**Action Map**](ActionsEditor.html#configure-action-maps) | Action Maps allow you to organise Actions into groups which represent specific situations where a set of actions make sense together. You can simultaneously enable or disable all Actions in an action map, so it is useful to group Actions in Action Maps by the context in which they are relevant. For example, you might have one action map for controlling a player, and another for interacting with your game's UI.|
|
||||
|[**Binding**](ActionBindings.html)| A connection defined between an **Action** and specific device controls. For example, your "Move" action might have bindings to the arrow keys and WSAD keys on the keyboard, and the left stick on a joypad, and the primary 2D axis on a VR controller. Multiple bindings like this means your game can accept cross-platform input. |
|
||||
|[**Your Action Code**](RespondingToActions.md)| The part of your script which is executed based on the actions you have configured. In your code, you can use references to actions to either read the current value or state of the action (also known as "polling"), or set up a callback to call your own method when actions are performed.|
|
||||
|[**Action Asset**](ActionAssets.md) | An asset type which contains a saved configuration of Action Maps, Actions and Bindings. You can specify one Action Asset in your project as the [project-wide actions](ProjectWideActions.md), which allows you to easily reference those actions in code by using [`InputSystem.actions`](../api/UnityEngine.InputSystem.InputSystem.html). |
|
@@ -0,0 +1,18 @@
|
||||
---
|
||||
uid: input-system-contributing
|
||||
---
|
||||
# Contributing
|
||||
|
||||
The [full source code](https://github.com/Unity-Technologies/InputSystem) for the Input System is available on GitHub. This is also where most of the Input System's development happens.
|
||||
|
||||
>__Note__: This includes the full source code for the managed/C# part of the system. At this point, the native, platform-specific C++ backends are still closed-source and require a source code license.
|
||||
|
||||
## Reporting bugs
|
||||
|
||||
To report documentation problems, please use the feedback section at the bottom of the page containing the problem.
|
||||
|
||||
To report bugs related to the Input System Please follow Unity's standard [bug reporting guidelines](https://unity3d.com/unity/qa/bug-reporting). Don't forget to submit a Project that the developer who picks up your report can use to reproduce the issue. Be sure to mention that the bug is specific to the Input System package in the description, so it gets forwarded to the correct team at Unity.
|
||||
|
||||
## Discussion
|
||||
|
||||
To ask questions or discuss the Input System, see the [dedicated section on Unity's forum](https://forum.unity.com/forums/new-input-system.103/). This is also the best place to post feature requests.
|
@@ -0,0 +1,285 @@
|
||||
---
|
||||
uid: input-system-controls
|
||||
---
|
||||
# Controls
|
||||
|
||||
* [Hierarchies](#control-hierarchies)
|
||||
* [Types](#control-types)
|
||||
* [Usages](#control-usages)
|
||||
* [Paths](#control-paths)
|
||||
* [State](#control-state)
|
||||
* [Actuation](#control-actuation)
|
||||
* [Noisy Controls](#noisy-controls)
|
||||
* [Synthetic Controls](#synthetic-controls)
|
||||
* [Performance Optimization](#performance-optimization)
|
||||
|
||||
An Input Control represents a source of values. These values can be of any structured or primitive type. The only requirement is that the type is [blittable](https://docs.microsoft.com/en-us/dotnet/framework/interop/blittable-and-non-blittable-types).
|
||||
|
||||
>__Note__: Controls are for input only. Output and configuration items on Input Devices are not represented as Controls.
|
||||
|
||||
Each Control is identified by a name ([`InputControl.name`](../api/UnityEngine.InputSystem.InputControl.html#UnityEngine_InputSystem_InputControl_name)) and can optionally have a display name ([`InputControl.displayName`](../api/UnityEngine.InputSystem.InputControl.html#UnityEngine_InputSystem_InputControl_displayName)) that differs from the Control name. For example, the right-hand face button closest to the touchpad on a PlayStation DualShock 4 controller has the control name "buttonWest" and the display name "Square".
|
||||
|
||||
Additionally, a Control might have one or more aliases which provide alternative names for the Control. You can access the aliases for a specific Control through its [`InputControl.aliases`](../api/UnityEngine.InputSystem.InputControl.html#UnityEngine_InputSystem_InputControl_aliases) property.
|
||||
|
||||
Finally, a Control might also have a short display name which can be accessed through the [`InputControl.shortDisplayName`](../api/UnityEngine.InputSystem.InputControl.html#UnityEngine_InputSystem_InputControl_shortDisplayName) property. For example, the short display name for the left mouse button is "LMB".
|
||||
|
||||
## Control hierarchies
|
||||
|
||||
Controls can form hierarchies. The root of a Control hierarchy is always a [Device](Devices.md).
|
||||
|
||||
The setup of hierarchies is exclusively controlled through [layouts](Layouts.md).
|
||||
|
||||
You can access the parent of a Control using [`InputControl.parent`](../api/UnityEngine.InputSystem.InputControl.html#UnityEngine_InputSystem_InputControl_parent), and its children using [`InputControl.children`](../api/UnityEngine.InputSystem.InputControl.html#UnityEngine_InputSystem_InputControl_children). To access the flattened hierarchy of all Controls on a Device, use [`InputDevice.allControls`](../api/UnityEngine.InputSystem.InputDevice.html#UnityEngine_InputSystem_InputDevice_allControls).
|
||||
|
||||
## Control types
|
||||
|
||||
All controls are based on the [`InputControl`](../api/UnityEngine.InputSystem.InputControl.html) base class. Most concrete implementations are based on [`InputControl<TValue>`](../api/UnityEngine.InputSystem.InputControl-1.html).
|
||||
|
||||
The Input System provides the following types of controls out of the box:
|
||||
|
||||
|Control Type|Description|Example|
|
||||
|------------|-----------|-------|
|
||||
|[`AxisControl`](../api/UnityEngine.InputSystem.Controls.AxisControl.html)|A 1D floating-point axis.|[`Gamepad.leftStick.x`](../api/UnityEngine.InputSystem.Controls.Vector2Control.html#UnityEngine_InputSystem_Controls_Vector2Control_x)|
|
||||
|[`ButtonControl`](../api/UnityEngine.InputSystem.Controls.ButtonControl.html)|A button expressed as a floating-point value. Whether the button can have a value other than 0 or 1 depends on the underlying representation. For example, gamepad trigger buttons can have values other than 0 and 1, but gamepad face buttons generally can't.|[`Mouse.leftButton`](../api/UnityEngine.InputSystem.Mouse.html#UnityEngine_InputSystem_Mouse_leftButton)|
|
||||
|[`KeyControl`](../api/UnityEngine.InputSystem.Controls.KeyControl.html)|A specialized button that represents a key on a [`Keyboard`](../api/UnityEngine.InputSystem.Keyboard.html). Keys have an associated [`keyCode`](../api/UnityEngine.InputSystem.Controls.KeyControl.html#UnityEngine_InputSystem_Controls_KeyControl_keyCode) and, unlike other types of Controls, change their display name in accordance to the currently active system-wide keyboard layout. See the [Keyboard](Keyboard.md) documentation for details.|[`Keyboard.aKey`](../api/UnityEngine.InputSystem.Keyboard.html#UnityEngine_InputSystem_Keyboard_aKey)|
|
||||
|[`Vector2Control`](../api/UnityEngine.InputSystem.Controls.Vector2Control.html)|A 2D floating-point vector.|[`Pointer.position`](../api/UnityEngine.InputSystem.Pointer.html#UnityEngine_InputSystem_Pointer_position)|
|
||||
|[`Vector3Control`](../api/UnityEngine.InputSystem.Controls.Vector3Control.html)|A 3D floating-point vector.|[`Accelerometer.acceleration`](../api/UnityEngine.InputSystem.Accelerometer.html#UnityEngine_InputSystem_Accelerometer_acceleration)|
|
||||
|[`QuaternionControl`](../api/UnityEngine.InputSystem.Controls.QuaternionControl.html)|A 3D rotation.|[`AttitudeSensor.attitude`](../api/UnityEngine.InputSystem.AttitudeSensor.html#UnityEngine_InputSystem_AttitudeSensor_attitude)|
|
||||
|[`IntegerControl`](../api/UnityEngine.InputSystem.Controls.IntegerControl.html)|An integer value.|[`Touchscreen.primaryTouch.touchId`](../api/UnityEngine.InputSystem.Controls.TouchControl.html#UnityEngine_InputSystem_Controls_TouchControl_touchId)|
|
||||
|[`StickControl`](../api/UnityEngine.InputSystem.Controls.StickControl.html)|A 2D stick control like the thumbsticks on gamepads or the stick control of a joystick.|[`Gamepad.rightStick`](../api/UnityEngine.InputSystem.Gamepad.html#UnityEngine_InputSystem_Gamepad_rightStick)|
|
||||
|[`DpadControl`](../api/UnityEngine.InputSystem.Controls.DpadControl.html)|A 4-way button control like the D-pad on gamepads or hatswitches on joysticks.|[`Gamepad.dpad`](../api/UnityEngine.InputSystem.Gamepad.html#UnityEngine_InputSystem_Gamepad_dpad)|
|
||||
|[`TouchControl`](../api/UnityEngine.InputSystem.Controls.TouchControl.html)|A control that represents all the properties of a touch on a [touch screen](Touch.md).|[`Touchscreen.primaryTouch`](../api/UnityEngine.InputSystem.Touchscreen.html#UnityEngine_InputSystem_Touchscreen_primaryTouch)|
|
||||
|
||||
You can browse the set of all registered control layouts in the [input debugger](Debugging.md#debugging-layouts).
|
||||
|
||||
## Control usages
|
||||
|
||||
A Control can have one or more associated usages. A usage is a string that denotes the Control's intended use. An example of a Control usage is `Submit`, which labels a Control that is commonly used to confirm a selection in the UI. On a gamepad, this usage is commonly found on the `buttonSouth` Control.
|
||||
|
||||
You can access a Control's usages using the [`InputControl.usages`](../api/UnityEngine.InputSystem.InputControl.html#UnityEngine_InputSystem_InputControl_usages) property.
|
||||
|
||||
Usages can be arbitrary strings. However, a certain set of usages is very commonly used and comes predefined in the API in the form of the [`CommonUsages`](../api/UnityEngine.InputSystem.CommonUsages.html) static class. Check out the [`CommonUsages` scripting API page](../api/UnityEngine.InputSystem.CommonUsages.html) for an overview.
|
||||
|
||||
## Control paths
|
||||
|
||||
>Example: `<Gamepad>/leftStick/x` means "X Control on left stick of gamepad".
|
||||
|
||||
The Input System can look up Controls using textual paths. [Bindings](ActionBindings.md) on Input Actions rely on this feature to identify the Control(s) they read input from. However, you can also use them for lookup directly on Controls and Devices, or to let the Input System search for Controls among all devices using [`InputSystem.FindControls`](../api/UnityEngine.InputSystem.InputSystem.html#UnityEngine_InputSystem_InputSystem_FindControls_System_String_).
|
||||
|
||||
```CSharp
|
||||
var gamepad = Gamepad.all[0];
|
||||
var leftStickX = gamepad["leftStick/x"];
|
||||
var submitButton = gamepad["{Submit}"];
|
||||
var allSubmitButtons = InputSystem.FindControls("*/{Submit}");
|
||||
```
|
||||
|
||||
Control paths resemble file system paths. Each path consists of one or more components separated by a forward slash:
|
||||
|
||||
component/component...
|
||||
|
||||
Each component uses a similar syntax made up of multiple fields. Each field is optional, but at least one field must be present. All fields are case-insensitive.
|
||||
|
||||
<layoutName>{usageName}controlName#(displayName)
|
||||
|
||||
The following table explains the use of each field:
|
||||
|
||||
|Field|Description|Example|
|
||||
|-----|-----------|-------|
|
||||
|`<layoutName>`|Requires the Control at the current level to be based on the given layout. The actual layout of the Control may be the same or a layout *based* on the given layout.|`<Gamepad>/buttonSouth`|
|
||||
|`{usageName}`|Works differently for Controls and Devices.<br><br>When used on a Device (the first component of a path), it requires the device to have the given usage. See [Device usages](Devices.md#device-usages) for more details.<br><br>For looking up a Control, the usage field is currently restricted to the path component immediately following the Device (the second component in the path). It finds the Control on the Device that has the given usage. The Control can be anywhere in the Control hierarchy of the Device.|Device:<br><br>`<XRController>{LeftHand}/trigger`<br><br>Control:<br><br>`<Gamepad>/{Submit}`|
|
||||
|`controlName`|Requires the Control at the current level to have the given name. Takes both "proper" names ([`InputControl.name`](../api/UnityEngine.InputSystem.InputControl.html#UnityEngine_InputSystem_InputControl_name)) and aliases ([`InputControl.aliases`](../api/UnityEngine.InputSystem.InputControl.html#UnityEngine_InputSystem_InputControl_aliases)) into account.<br><br>This field can also be a wildcard (`*`) to match any name.|`MyGamepad/buttonSouth`<br><br>`*/{PrimaryAction}` (match `PrimaryAction` usage on Devices with any name)|
|
||||
|`#(displayName)`|Requires the Control at the current level to have the given display name (i.e. [`InputControl.displayName`](../api/UnityEngine.InputSystem.InputControl.html#UnityEngine_InputSystem_InputControl_displayName)). The display name may contain whitespace and symbols.|`<Keyboard>/#(a)` (matches the key that generates the "a" character, if any, according to the current keyboard layout).<br><br>`<Gamepad>/#(Cross)`|
|
||||
|
||||
You can access the literal path of a given control via its [`InputControl.path`](../api/UnityEngine.InputSystem.InputControl.html#UnityEngine_InputSystem_InputControl_path) property.
|
||||
|
||||
If needed, you can manually parse a control path into its components using the [`InputControlPath.Parse(path)`](../api/UnityEngine.InputSystem.InputControlPath.html#UnityEngine_InputSystem_InputControlPath_Parse_System_String_) API.
|
||||
|
||||
```CSharp
|
||||
var parsed = InputControlPath.Parse("<XRController>{LeftHand}/trigger").ToArray();
|
||||
|
||||
Debug.Log(parsed.Length); // Prints 2.
|
||||
Debug.Log(parsed[0].layout); // Prints "XRController".
|
||||
Debug.Log(parsed[0].name); // Prints an empty string.
|
||||
Debug.Log(parsed[0].usages.First()); // Prints "LeftHand".
|
||||
Debug.Log(parsed[1].layout); // Prints null.
|
||||
Debug.Log(parsed[1].name); // Prints "trigger".
|
||||
```
|
||||
|
||||
## Control state
|
||||
|
||||
Each Control is connected to a block of memory that is considered the Control's "state". You can query the size, format, and location of this block of memory from a Control through the [`InputControl.stateBlock`](../api/UnityEngine.InputSystem.InputControl.html#UnityEngine_InputSystem_InputControl_stateBlock) property.
|
||||
|
||||
The state of Controls is stored in unmanaged memory that the Input System handles internally. All Devices added to the system share one block of unmanaged memory that contains the state of all the Controls on the Devices.
|
||||
|
||||
A Control's state might not be stored in the natural format for that Control. For example, the system often represents buttons as bitfields, and axis controls as 8-bit or 16-bit integer values. This format is determined by the combination of platform, hardware, and drivers. Each Control knows the format of its storage and how to translate the values as needed. The Input System uses [layouts](Layouts.md) to understand this representation.
|
||||
|
||||
You can access the current state of a Control through its [`ReadValue`](../api/UnityEngine.InputSystem.InputControl-1.html#UnityEngine_InputSystem_InputControl_1_ReadValue) method.
|
||||
|
||||
```CSharp
|
||||
Gamepad.current.leftStick.x.ReadValue();
|
||||
```
|
||||
|
||||
Each type of Control has a specific type of values that it returns, regardless of how many different types of formats it supports for its state. You can access this value type through the [`InputControl.valueType`](../api/UnityEngine.InputSystem.InputControl.html#UnityEngine_InputSystem_InputControl_valueType) property.
|
||||
|
||||
Reading a value from a Control might apply one or more value Processors. See documentation on [Processors](Processors.md) for more information.
|
||||
|
||||
[//]: # (#### Default State - TODO)
|
||||
|
||||
[//]: # (#### Reading State vs Reading Values - TODO)
|
||||
|
||||
#### Recording state history
|
||||
|
||||
You might want to access the history of value changes on a Control (for example, in order to compute exit velocity on a touch release).
|
||||
|
||||
To record state changes over time, you can use [`InputStateHistory`](../api/UnityEngine.InputSystem.LowLevel.InputStateHistory.html) or [`InputStateHistory<TValue>`](../api/UnityEngine.InputSystem.LowLevel.InputStateHistory-1.html). The latter restricts Controls to those of a specific value type, which in turn simplifies some of the API.
|
||||
|
||||
```CSharp
|
||||
// Create history that records Vector2 control value changes.
|
||||
// NOTE: You can also pass controls directly or use paths that match multiple
|
||||
// controls (e.g. "<Gamepad>/<Button>").
|
||||
// NOTE: The unconstrained InputStateHistory class can record changes on controls
|
||||
// of different value types.
|
||||
var history = new InputStateHistory<Vector2>("<Touchscreen>/primaryTouch/position");
|
||||
|
||||
// To start recording state changes of the controls to which the history
|
||||
// is attached, call StartRecording.
|
||||
history.StartRecording();
|
||||
|
||||
// To stop recording state changes, call StopRecording.
|
||||
history.StopRecording();
|
||||
|
||||
// Recorded history can be accessed like an array.
|
||||
for (var i = 0; i < history.Count; ++i)
|
||||
{
|
||||
// Each recorded value provides information about which control changed
|
||||
// value (in cases state from multiple controls is recorded concurrently
|
||||
// by the same InputStateHistory) and when it did so.
|
||||
|
||||
var time = history[i].time;
|
||||
var control = history[i].control;
|
||||
var value = history[i].ReadValue();
|
||||
}
|
||||
|
||||
// Recorded history can also be iterated over.
|
||||
foreach (var record in history)
|
||||
Debug.Log(record.ReadValue());
|
||||
Debug.Log(string.Join(",\n", history));
|
||||
|
||||
// You can also record state changes manually, which allows
|
||||
// storing arbitrary histories in InputStateHistory.
|
||||
// NOTE: This records a value change that didn't actually happen on the control.
|
||||
history.RecordStateChange(Touchscreen.current.primaryTouch.position,
|
||||
new Vector2(0.123f, 0.234f));
|
||||
|
||||
// State histories allocate unmanaged memory and need to be disposed.
|
||||
history.Dispose();
|
||||
```
|
||||
|
||||
For example, if you want to have the last 100 samples of the left stick on the gamepad available, you can use this code:
|
||||
|
||||
```CSharp
|
||||
var history = new InputStateHistory<Vector2>(Gamepad.current.leftStick);
|
||||
history.historyDepth = 100;
|
||||
history.StartRecording();
|
||||
```
|
||||
|
||||
## Control actuation
|
||||
|
||||
A Control is considered actuated when it has moved away from its default state in such a way that it affects the actual value of the Control. You can query whether a Control is currently actuated using [`IsActuated`](../api/UnityEngine.InputSystem.InputControlExtensions.html#UnityEngine_InputSystem_InputControlExtensions_IsActuated_UnityEngine_InputSystem_InputControl_System_Single_).
|
||||
|
||||
```CSharp
|
||||
// Check if leftStick is currently actuated.
|
||||
if (Gamepad.current.leftStick.IsActuated())
|
||||
Debug.Log("Left Stick is actuated");
|
||||
```
|
||||
|
||||
It can be useful to determine not just whether a Control is actuated at all, but also the amount by which it is actuated (that is, its magnitude). For example, for a [`Vector2Control`](../api/UnityEngine.InputSystem.Controls.Vector2Control.html) this would be the length of the vector, whereas for a button it is the raw, absolute floating-point value.
|
||||
|
||||
In general, the current magnitude of a Control is always >= 0. However, a Control might not have a meaningful magnitude, in which case it returns -1. Any negative value should be considered an invalid magnitude.
|
||||
|
||||
You can query the current amount of actuation using [`EvaluateMagnitude`](../api/UnityEngine.InputSystem.InputControl.html#UnityEngine_InputSystem_InputControl_EvaluateMagnitude).
|
||||
|
||||
```CSharp
|
||||
// Check if left stick is actuated more than a quarter of its motion range.
|
||||
if (Gamepad.current.leftStick.EvaluateMagnitude() > 0.25f)
|
||||
Debug.Log("Left Stick actuated past 25%");
|
||||
```
|
||||
|
||||
There are two mechanisms that most notably make use of Control actuation:
|
||||
|
||||
- [Interactive rebinding](ActionBindings.md#interactive-rebinding) (`InputActionRebindingExceptions.RebindOperation`) uses it to select between multiple suitable Controls to find the one that is actuated the most.
|
||||
- [Conflict resolution](ActionBindings.md#conflicting-inputs) between multiple Controls that are bound to the same action uses it to decide which Control gets to drive the action.
|
||||
|
||||
## Noisy Controls
|
||||
|
||||
The Input System can label a Control as "noisy". You can query this using the [`InputControl.noisy`](../api/UnityEngine.InputSystem.InputControl.html#UnityEngine_InputSystem_InputControl_noisy) property.
|
||||
|
||||
Noisy Controls are those that can change value without any actual or intentional user interaction required. A good example of this is a gravity sensor in a cellphone. Even if the cellphone is perfectly still, there are usually fluctuations in gravity readings. Another example are orientation readings from an HMD.
|
||||
|
||||
If a Control is marked as noisy, it means that:
|
||||
|
||||
1. The Control is not considered for [interactive rebinding](ActionBindings.md#interactive-rebinding). [`InputActionRebindingExceptions.RebindingOperation`](../api/UnityEngine.InputSystem.InputActionRebindingExtensions.RebindingOperation.html) ignores the Control by default (you can bypass this using [`WithoutIgnoringNoisyControls`](../api/UnityEngine.InputSystem.InputActionRebindingExtensions.RebindingOperation.html#UnityEngine_InputSystem_InputActionRebindingExtensions_RebindingOperation_WithoutIgnoringNoisyControls)).
|
||||
2. If enabled in the Project Settings, the system performs additional event filtering, then calls [`InputDevice.MakeCurrent`](../api/UnityEngine.InputSystem.InputDevice.html#UnityEngine_InputSystem_InputDevice_MakeCurrent). If an input event for a Device contains no state change on a Control that is not marked noisy, then the Device will not be made current based on the event. This avoids, for example, a plugged in PS4 controller constantly making itself the current gamepad ([`Gamepad.current`](../api/UnityEngine.InputSystem.Gamepad.html#UnityEngine_InputSystem_Gamepad_current)) due to its sensors constantly feeding data into the system.
|
||||
3. When the application loses focus and Devices are [reset](Devices.md#device-resets) as a result, the state of noisy Controls will be preserved as is. This ensures that sensor readinds will remain at their last value rather than being reset to default values.
|
||||
|
||||
>**Note**: If any Control on a Device is noisy, the Device itself is flagged as noisy.
|
||||
|
||||
Parallel to the [`input state`](../api/UnityEngine.InputSystem.InputControl.html#UnityEngine_InputSystem_InputControl_currentStatePtr) and the [`default state`](../api/UnityEngine.InputSystem.InputControl.html#UnityEngine_InputSystem_InputControl_defaultStatePtr) that the Input System keeps for all Devices currently present, it also maintains a [`noise mask`](../api/UnityEngine.InputSystem.InputControl.html#UnityEngine_InputSystem_InputControl_noiseMaskPtr) in which only bits for state that is __not__ noise are set. This can be used to very efficiently mask out noise in input.
|
||||
|
||||
## Synthetic Controls
|
||||
|
||||
A synthetic Control is a Control that doesn't correspond to an actual physical control on a device (for example the `left`, `right`, `up`, and `down` child Controls on a [`StickControl`](../api/UnityEngine.InputSystem.Controls.StickControl.html)). These Controls synthesize input from other, actual physical Controls and present it in a different way (in this example, they allow you to treat the individual directions of a stick as buttons).
|
||||
|
||||
Whether a given Control is synthetic is indicated by its [`InputControl.synthetic`](../api/UnityEngine.InputSystem.InputControl.html#UnityEngine_InputSystem_InputControl_synthetic) property.
|
||||
|
||||
The system considers synthetic Controls for [interactive rebinding](ActionBindings.md#interactive-rebinding) but always favors non-synthetic Controls. If both a synthetic and a non-synthetic Control that are a potential match exist, the non-synthetic Control wins by default. This makes it possible to interactively bind to `<Gamepad>/leftStick/left`, for example, but also makes it possible to bind to `<Gamepad>/leftStickPress` without getting interference from the synthetic buttons on the stick.
|
||||
|
||||
## Performance Optimization
|
||||
|
||||
### Avoiding defensive copies
|
||||
|
||||
Use [`InputControl<T>.value`](../api/UnityEngine.InputSystem.InputControl-1.html#UnityEngine_InputSystem_InputControl_1_value) instead of [`InputControl<T>.ReadValue`](../api/UnityEngine.InputSystem.InputControl-1.html#UnityEngine_InputSystem_InputControl_1_ReadValue) to avoid creating a copy of the control state on every call, as the former returns the value as `ref readonly` while the latter always makes a copy. Note that this optimization only applies if the call site assigns the return value to a variable that has been declared 'ref readonly'. Otherwise a copy will be made as before. Additionally, be aware of defensive copies that can be allocated by the compiler when it is unable to determine that it can safely use the readonly reference i.e. if it can't determine that the reference won't be changed, it will create a defensive copy for you. For more details, see https://learn.microsoft.com/en-us/dotnet/csharp/write-safe-efficient-code#use-ref-readonly-return-statements.
|
||||
|
||||
|
||||
### Control Value Caching
|
||||
|
||||
When the `'USE_READ_VALUE_CACHING'` internal feature flag is set, the Input System will switch to an optimized path for reading control values. This path efficiently marks controls as 'stale' when they have been actuated. Subsequent calls to [`InputControl<T>.ReadValue`](../api/UnityEngine.InputSystem.InputControl-1.html#UnityEngine_InputSystem_InputControl_1_ReadValue) will only apply control processing when there have been changes to that control or in case of control processing. Control processing in this case can mean any hard-coded processing that might exist on the control, such as with [`AxisControl`](../api/UnityEngine.InputSystem.Controls.AxisControl.html) which has built-in inversion, normalisation, scaling etc, or any processors that have been applied to the controls' [processor stack](Processors.md#processors-on-controls).
|
||||
> Note: Performance improvements **are currently not guaranteed** for all use cases. Even though this performance path marks controls as "stale" in an efficient way, it still has an overhead which can degrade performance in some cases.
|
||||
|
||||
A positive performance impact has been seen when:
|
||||
- Reading from controls that do not change frequently.
|
||||
- In case the controls change every frame, are being read and have actions bound to them as well, e.g. on a Gamepad, reading `leftStick`, `leftStick.x` and `leftStick.left` for example when there's a action with composite bindings setup.
|
||||
|
||||
On the other hand, it is likely to have a negative performance impact when:
|
||||
- No control reads are performed for a control, and there are a lot of changes for that particular control.
|
||||
- Reading from controls that change frequently that have no actions bound to those controls.
|
||||
|
||||
Moreover, this feature is not enabled by default as it can result in the following minor behavioural changes:
|
||||
* Some control processors use global state. Without cached value optimizations, it is possible to read the control value, change the global state, read the control value again, and get a new value due to the fact that the control processor runs on every call. With cached value optimizations, reading the control value will only ever return a new value if the physical control has been actuated. Changing the global state of a control processor will have no effect otherwise.
|
||||
* Writing to device state using low-level APIs like [`InputControl<T>.WriteValueIntoState`](../api/UnityEngine.InputSystem.InputControl-1.html#UnityEngine_InputSystem_InputControl_1_WriteValueIntoState__0_System_Void__) does not set the stale flag and subsequent calls to [`InputControl<T>.value`](../api/UnityEngine.InputSystem.InputControl-1.html#UnityEngine_InputSystem_InputControl_1_value) will not reflect those changes.
|
||||
* After changing properties on [`AxisControl`](../api/UnityEngine.InputSystem.Controls.AxisControl.html) the [`ApplyParameterChanges`](../api/UnityEngine.InputSystem.InputControl.html#UnityEngine_InputSystem_InputControl_ApplyParameterChanges) has to be called to invalidate cached value.
|
||||
|
||||
Processors that need to run on every read can set their respective caching policy to EvaluateOnEveryRead. That will disable caching on controls that are using such processor.
|
||||
|
||||
If there are any non-obvious inconsistencies, 'PARANOID_READ_VALUE_CACHING_CHECKS' internal feature flag can be enabled to compare cached and uncached value on every read and log an error if they don't match.
|
||||
|
||||
### Optimized control read value
|
||||
|
||||
When the `'USE_OPTIMIZED_CONTROLS'` internal feature flag is set, the Input System will use faster way to use state memory for some controls instances. This is very specific optimization and should be used with caution.
|
||||
|
||||
> __Please note__: This optimization has a performance impact on `PlayMode` as we do extra checks to ensure that the controls have the correct memory representation during development. Don't be alarmed if you see a performance drop in `PlayMode` when using this optimization as it's expected at this stage.
|
||||
|
||||
Most controls are flexible with regards to memory representation, like [`AxisControl`](../api/UnityEngine.InputSystem.Controls.AxisControl.html) can be one bit, multiple bits, a float, etc, or in [`Vector2Control`](../api/UnityEngine.InputSystem.Controls.Vector2Control.html) where x and y can have different memory representation.
|
||||
Yet for most controls there are common memory representation patterns, for example [`AxisControl`](../api/UnityEngine.InputSystem.Controls.AxisControl.html) are floats or single bytes. Or some [`Vector2Control`](../api/UnityEngine.InputSystem.Controls.Vector2Control.html) are two consequitive floats in memory.
|
||||
If a control matches a common representation we can bypass reading its children control and cast the memory directly to the common representation. For example if [`Vector2Control`](../api/UnityEngine.InputSystem.Controls.Vector2Control.html) is two consecutive floats in memory we can bypass reading `x` and `y` separately and just cast the state memory to `Vector2`.
|
||||
|
||||
> __Please note__: This optimization only works if the controls don't need any processing applied to them, such as `invert`, `clamp`, `normalize`, `scale` or any other processor. If any of these are applied to the control, **there won't be any optimization applied** and the control will be read as usual.
|
||||
|
||||
Also, [`InputControl.ApplyParameterChanges()`](../api/UnityEngine.InputSystem.InputControl.html#UnityEngine_InputSystem_InputControl_ApplyParameterChanges) **must be explicitly called** in specific changes to ensure [`InputControl.optimizedControlDataType`](../api/UnityEngine.InputSystem.InputControl.html#UnityEngine_InputSystem_InputControl_optimizedControlDataType) is updated to the correct memory representation. Make sure to call it when:
|
||||
* Configuration changes after [`InputControl.FinishSetup()`](../api/UnityEngine.InputSystem.InputControl.html#UnityEngine_InputSystem_InputControl_FinishSetup_) is called.
|
||||
* Changing parameters such [`AxisControl.invert`](../api/UnityEngine.InputSystem.Controls.AxisControl.html#UnityEngine_InputSystem_Controls_AxisControl_invert), [`AxisControl.clamp`](../api/UnityEngine.InputSystem.Controls.AxisControl.html#UnityEngine_InputSystem_Controls_AxisControl_clamp), [`AxisControl.normalize`](../api/UnityEngine.InputSystem.Controls.AxisControl.html#UnityEngine_InputSystem_Controls_AxisControl_normalize), [`AxisControl.scale`](../api/UnityEngine.InputSystem.Controls.AxisControl.html#UnityEngine_InputSystem_Controls_AxisControl_scale) or changing processors. The memory representation needs to be recalculated after these changes so that we know that the control is not optimized anymore. Otherwise, the control will be read with wrong values.
|
||||
|
||||
The optimized controls work as follows:
|
||||
* A potential memory representation is set using [`InputControl.CalculateOptimizedControlDataType()`](../api/UnityEngine.InputSystem.InputControl.html#UnityEngine_InputSystem_InputControl_CalculateOptimizedControlDataType)
|
||||
* Its memory representation is stored in [`InputControl.optimizedControlDataType`](../api/UnityEngine.InputSystem.InputControl.html#UnityEngine_InputSystem_InputControl_optimizedControlDataType)
|
||||
* Finally, [`ReadUnprocessedValueFromState`](../api/UnityEngine.InputSystem.InputControl-1.html#UnityEngine_InputSystem_InputControl_1_ReadUnprocessedValueFromState_) uses the optimized memory representation to decide if it should cast to memory directly instead of reading every children control on it's own to reconstruct the controls state.
|
@@ -0,0 +1,176 @@
|
||||
---
|
||||
uid: input-system-debugging
|
||||
---
|
||||
# Debugging
|
||||
|
||||
- [Debugging](#debugging)
|
||||
- [Input Debugger](#input-debugger)
|
||||
- [Debugging Devices](#debugging-devices)
|
||||
- [Debugging Actions](#debugging-actions)
|
||||
- [Debugging users and PlayerInput](#debugging-users-and-playerinput)
|
||||
- [Debugging layouts](#debugging-layouts)
|
||||
- [Debugging remotely](#debugging-remotely)
|
||||
- [Input visualizers](#input-visualizers)
|
||||
- [`InputControlVisualizer`](#inputcontrolvisualizer)
|
||||
- [`InputActionVisualizer`](#inputactionvisualizer)
|
||||
- [Device Simulator](#device-simulator)
|
||||
- [Unity Remote (iOS, Android)](#unity-remote)
|
||||
- [Other tips:](#other-tips)
|
||||
|
||||
When something isn't working as expected, the quickest way to troubleshoot what's wrong is the Input Debugger in the Unity Editor. The Input Debugger provides access to the activity of the Input System in both the Editor and the connected Players.
|
||||
|
||||
To open the Input Debugger, go to __Window > Analysis > Input Debugger__ from Unity's main menu.
|
||||
|
||||
## Input Debugger
|
||||
|
||||

|
||||
|
||||
The Input Debugger displays a tree breakdown of the state of the Input System.
|
||||
|
||||
|Item|Description|
|
||||
|----|-----------|
|
||||
|Devices|A list of all [Input Devices](Devices.md) that are currently in the system, and a list of unsupported/unrecognized Devices.|
|
||||
|Layouts|A list of all registered Control and Device layouts. This is the database of supported hardware, and information on how to represent a given piece of input hardware.|
|
||||
|Actions|Only visible in Play mode, and only if at least one [Action](Actions.md) is enabled.<br><br>A list of all currently enabled Actions, and the Controls they are bound to.<br><br>See [Debugging Actions](#debugging-actions).|
|
||||
|Users|Only visible when one or more `InputUser` instances exist. See documentation on [user management](UserManagement.md).<br><br>A list of all currently active users, along with their active Control Schemes and Devices, all their associated Actions, and the Controls these Actions are bound to.<br><br>Note that `PlayerInput` uses `InputUser` to run. When using `PlayerInput` components, each player has an entry in this list.<br><br>See [Debugging users and PlayerInput](#debugging-users-and-playerinput).|
|
||||
|Settings|The currently active Input System [settings](Settings.md).|
|
||||
|Metrics|Statistics about Input System resource usage.|
|
||||
|
||||
### Debugging Devices
|
||||
|
||||
In the Input Debugger window, navigate to the __Devices__ list and double-click any [Input Device](Devices.md). This opens a window that displays information about the Device, including real-time state information for its Controls.
|
||||
|
||||

|
||||
|
||||
The top of the Device window displays general information about the specific Device, such as name, manufacturer, and serial number.
|
||||
|
||||
The __Controls__ section lists the Device's Controls and their individual states. This is useful when debugging input issues, because you can verify whether the data that the Input System receives from the Input Device is what you expect it to be. There are two buttons at the top of this panel:
|
||||
|
||||
* __HID Descriptor__: Only displayed for devices that use the HID protocol to connect. This opens a window that displays the detailed [HID](HID.md) specifications for the Device and each of it's logical controls.
|
||||
|
||||
* __State__: Display the current state of the Device in a new window. This is identical to the information displayed in this view, but doesn't update in real time, so you can take a snapshot of input state data and take the time to inspect it as needed.
|
||||
|
||||
The __Events__ section lists all [input events](Events.md) generated by the Device. You can double-click any event in the list to inspect the full Device state at the time the event occurred. To get a side-by-side difference between the state of the Device at different points in time, select multiple events, right-click them, and click __Compare__ from the context menu.
|
||||
|
||||
### Debugging Actions
|
||||
|
||||
The Input Debugger window lists all enabled [Actions](Actions.md) in the __Actions__ list. This list only appears if at least one Action is active and the Editor is in Play mode. If an Action has actively bound Controls, you can click the arrow next to the Action to see a list of the Controls. This is useful to debug whether your Bindings correctly map to the Controls you want them to bind to. See documentation on [Binding resolution](ActionBindings.md#binding-resolution) for more information about how Unity maps Bindings to Controls.
|
||||
|
||||
>__Note__: Actions that belong to [`InputUsers`](UserManagement.md) don't appear here. They appear in the [__Users__](#debugging-users-and-playerinput) list instead.
|
||||
|
||||
### Debugging users and PlayerInput
|
||||
|
||||
When there are [`InputUser`](UserManagement.md) instances (if you use `PlayerInput`, each `PlayerInput` instance implicitly creates one), the Input Debugger's __Users__ list displays each instance along with its paired Devices and active Actions. The listed Devices and Actions work the same way as those displayed in the [__Devices__](#debugging-devices) and [__Actions__](#debugging-actions) lists in the debugging window.
|
||||
|
||||

|
||||
|
||||
### Debugging layouts
|
||||
|
||||
The [__Layouts__](Layouts.md) list in the Input Debugger window displays a breakdown of all registered [Control and Device layouts](Layouts.md). This is the database of supported hardware and the knowledge of how to represent a given piece of input hardware. It's useful when you want to [create a new Device mapping](HID.md#creating-a-custom-device-layout) and see how the Input System represents it.
|
||||
|
||||

|
||||
|
||||
### Debugging remotely
|
||||
|
||||
You can connect the Input Debugger to a Player that runs on a remote computer or device. This makes it possible to observe input activity from the Player in the Editor. This connection uses the `PlayerConnection` mechanism, which is the same one the Unity profiler uses to connect to a Player.
|
||||
|
||||
>__Note__: At the moment, debugging input in Players is restricted to seeing Devices and events from connected Players. There is no support for seeing other input-related data such as Actions and input users from Players.
|
||||
|
||||
To see remote Devices from built Players, open the Input Debugger window's __Remote Devices__ drop-down list. This list displays the remote Player instance you can connect to (if there are any). The same list appears in the Profiler and Console windows, and any connections are shared between those windows. If any Player(s) are connected, you can enable __Show remote devices__ in the same drop-down list. If Players are connected, and __Show remote devices__ is enabled, the [__Devices__](#debugging-devices) list in the Input Debugger window splits into a __Local__ section and a __Remote__ section. The __Remote__ section displays any Input Device from any connected Player, and lets you inspect Device state and events in real time, as if it were a local Device.
|
||||
|
||||
## Input visualizers
|
||||
|
||||
The Input System package comes with a __Visualizers__ sample, which provides various components which let you monitor the state of various Input System elements in real time using on-screen visualizers.
|
||||
|
||||
To install the sample, navigate to the Input System package in the Package Manager window (see [Installation](Installation.md)), and next to the __Visualizers__ sample, click __Import in project__.
|
||||
|
||||
The sample provides two visualizer components:
|
||||
|
||||
### `InputControlVisualizer`
|
||||
|
||||
Visualizes the current state of a single Control in real time. You can have multiple Control visualizers to visualize the state of multiple Controls. Check the `GamepadVisualizer`, `MouseVisualizer`, or `PenVisualizer` Scenes in the sample for examples.
|
||||
|
||||

|
||||
|
||||
### `InputActionVisualizer`
|
||||
|
||||
Visualizes the current state of a single Action in real time. You can have multiple Action visualizers to visualize the state of multiple Actions. This can also display the current value of the Action and the Control currently driving the Action, and track the state of [Interactions](Interactions.md) over time. Check the `SimpleControlsVisualizer` Scene in the sample for examples.
|
||||
|
||||

|
||||
|
||||
## Device Simulator
|
||||
|
||||
When Device Simulator window is in use, mouse and pen inputs on the simulated device screen are turned into touchscreen inputs. Device Simulator uses its own touchscreen device, which it creates and destroys together with the Device Simulator window.
|
||||
|
||||
To prevent conflicts between simulated touchscreen inputs and native mouse and pen inputs, Device Simulator disables all native mouse and pen devices.
|
||||
|
||||
## Unity Remote
|
||||
|
||||
The Unity Remote is an app available for iOS and Android which allows using a mobile device for input while running in the Unity Editor. You can find details about the app and how to install it in the [Unity manual](https://docs.unity3d.com/Manual/UnityRemote5.html).
|
||||
|
||||
If you would like to try out the Unity Remote app, you can [install](Installation.md#installing-samples) the "Unity Remote" sample that is provided with the Input System package.
|
||||
|
||||
>__Note__: Joysticks/gamepads are not yet supported over the Unity Remote. No joystick/gamepad input from the mobile device will come through in the editor.
|
||||
|
||||
>__Note__: This requires Unity 2021.2.18 or later.
|
||||
|
||||
When in play mode in the Editor and connected to the Unity Remote app, you will see a number of Devices have been added with the [`InputDevice.remote`](../api/UnityEngine.InputSystem.InputDevice.html#UnityEngine_InputSystem_InputDevice_remote) flag set to true:
|
||||
|
||||
- [`Touchscreen`](../api/UnityEngine.InputSystem.Touchscreen.html)
|
||||
- [`Accelerometer`](../api/UnityEngine.InputSystem.Accelerometer.html)
|
||||
|
||||
If a gyro is present on the mobile device:
|
||||
|
||||
- [`Gyroscope`](../api/UnityEngine.InputSystem.Gyroscope.html)
|
||||
- [`AttitudeSensor`](../api/UnityEngine.InputSystem.AttitudeSensor.html)
|
||||
- [`LinearAccelerationSensor`](../api/UnityEngine.InputSystem.LinearAccelerationSensor.html)
|
||||
- [`GravitySensor`](../api/UnityEngine.InputSystem.GravitySensor.html)
|
||||
|
||||
These Devices can be used just like local Devices. They will receive input from the connected mobile device which in turn will receive the rendered output of the game running in the editor.
|
||||
|
||||
The [`Accelerometer`](../api/UnityEngine.InputSystem.Accelerometer.html) device will automatically be enabled and will not need you to call [`InputSystem.EnableDevice`](../api/UnityEngine.InputSystem.InputSystem.html#UnityEngine_InputSystem_InputSystem_EnableDevice_UnityEngine_InputSystem_InputDevice_) explicitly. Setting the sampling frequency on the accelerometer from the Unity Remote using [`Sensor.samplingFrequency`](../api/UnityEngine.InputSystem.Sensor.html#UnityEngine_InputSystem_Sensor_samplingFrequency) has no effect.
|
||||
|
||||
The remaining sensors listed above will need to be explicitly enabled via [`InputSystem.EnableDevice`](../api/UnityEngine.InputSystem.InputSystem.html#UnityEngine_InputSystem_InputSystem_EnableDevice_UnityEngine_InputSystem_InputDevice_) just like local sensors. Setting the sampling frequency on these sensors from the Unity Remote using [`Sensor.samplingFrequency`](../api/UnityEngine.InputSystem.Sensor.html#UnityEngine_InputSystem_Sensor_samplingFrequency) will be relayed to the device but note that setting the frequency on one of them will set it for all of them.
|
||||
|
||||
Touch coordinates from the device will be translated to the screen coordinates of the Game View inside the Editor.
|
||||
|
||||
## Other tips:
|
||||
|
||||
To record events flowing through the system, use this code:
|
||||
|
||||
```C#
|
||||
|
||||
// You can also provide a device ID to only
|
||||
// trace events for a specific device.
|
||||
var trace = new InputEventTrace();
|
||||
|
||||
trace.Enable();
|
||||
|
||||
var current = new InputEventPtr();
|
||||
while (trace.GetNextEvent(ref current))
|
||||
{
|
||||
Debug.Log("Got some event: " + current);
|
||||
}
|
||||
|
||||
// Also supports IEnumerable.
|
||||
foreach (var eventPtr in trace)
|
||||
Debug.Log("Got some event: " + eventPtr);
|
||||
|
||||
// Trace consumes unmanaged resources. Make sure you dispose it correctly to avoid memory leaks.
|
||||
trace.Dispose();
|
||||
|
||||
```
|
||||
|
||||
To see events as they're processed, use this code:
|
||||
|
||||
```C#
|
||||
|
||||
InputSystem.onEvent +=
|
||||
(eventPtr, device) =>
|
||||
{
|
||||
// Can handle events yourself, for example, and then stop them
|
||||
// from further processing by marking them as handled.
|
||||
eventPtr.handled = true;
|
||||
};
|
||||
|
||||
```
|
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"folders": [
|
||||
{
|
||||
"path": "."
|
||||
}
|
||||
],
|
||||
"settings": {
|
||||
}
|
||||
}
|
@@ -0,0 +1,18 @@
|
||||
---
|
||||
uid: input-system-editor-features
|
||||
---
|
||||
# Input System Editor Features
|
||||
|
||||
This section describes how the Input System integrates with the Unity Editor, which allows you to read input in edit mode, debug input values, and set up automated input tests.
|
||||
|
||||
### [Using Input in the Editor](UseInEditor.md)
|
||||
|
||||
Unlike Unity's old Input Manager, the Input System package allows you to read input from within [Editor window code](https://docs.unity3d.com/Manual/editor-EditorWindows.html) as well. ([Read more](UseInEditor.md))
|
||||
|
||||
### [The Input Debugger](Debugging.md)
|
||||
|
||||
When something isn't working as expected, the quickest way to troubleshoot what's wrong is the Input Debugger in the Unity Editor. The Input Debugger provides access to the activity of the Input System in both the Editor and the connected Players. ([Read more](Debugging.md))
|
||||
|
||||
### [Automated Input Testing](Testing.md)
|
||||
|
||||
The Input System has built-in support for writing automated input tests. You can drive input entirely from code, without any dependencies on platform backends and physical hardware devices. The automated input tests you write consider the generated input to be the same as input generated at runtime by actual platform code. ([Read more](Testing.md))
|
@@ -0,0 +1,328 @@
|
||||
---
|
||||
uid: input-system-events
|
||||
---
|
||||
# Input events
|
||||
|
||||
* [Types of events](#types-of-events)
|
||||
* [State events](#state-events)
|
||||
* [Device events](#device-events)
|
||||
* [Text events](#text-events)
|
||||
* [Working with events](#working-with-events)
|
||||
* [Listening to events](#listening-to-events)
|
||||
* [Reading state events](#reading-state-events)
|
||||
* [Creating events](#creating-events)
|
||||
* [Capturing events](#capturing-events)
|
||||
* [Processing events](#processing-events)
|
||||
* [Merging of events](#merging-of-events)
|
||||
|
||||
The Input System is event-driven. All input is delivered as events, and you can generate custom input by injecting events. You can also observe all source input by listening in on the events flowing through the system.
|
||||
|
||||
>__Note__: Events are an advanced, mostly internal feature of the Input System. Knowledge of the event system is mostly useful if you want to support custom Devices, or change the behavior of existing Devices.
|
||||
|
||||
Input events are a low-level mechanism. Usually, you don't need to deal with events if all you want to do is receive input for your app. Events are stored in unmanaged memory buffers and not converted to C# heap objects. The Input System provides wrapper APIs, but unsafe code is required for more involved event manipulations.
|
||||
|
||||
Note that there are no routing mechanism. The runtime delivers events straight to the Input System, which then incorporates them directly into the Device state.
|
||||
|
||||
Input events are represented by the [`InputEvent`](../api/UnityEngine.InputSystem.LowLevel.InputEvent.html) struct. Each event has a set of common properties:
|
||||
|
||||
|Property|Description|
|
||||
|--------|-----------|
|
||||
|[`type`](../api/UnityEngine.InputSystem.LowLevel.InputEvent.html#UnityEngine_InputSystem_LowLevel_InputEvent_type)|[`FourCC`](../api/UnityEngine.InputSystem.Utilities.FourCC.html) code that indicates what type of event it is.|
|
||||
|[`eventId`](../api/UnityEngine.InputSystem.LowLevel.InputEvent.html#UnityEngine_InputSystem_LowLevel_InputEvent_eventId)|Unique numeric ID of the event.|
|
||||
|[`time`](../api/UnityEngine.InputSystem.LowLevel.InputEvent.html#UnityEngine_InputSystem_LowLevel_InputEvent_time)|Timestamp of when the event was generated. This is on the same timeline as [`Time.realtimeSinceStartup`](https://docs.unity3d.com/ScriptReference/Time-realtimeSinceStartup.html).|
|
||||
|[`deviceId`](../api/UnityEngine.InputSystem.LowLevel.InputEvent.html#UnityEngine_InputSystem_LowLevel_InputEvent_deviceId)|ID of the Device that the event targets.|
|
||||
|[`sizeInBytes`](../api/UnityEngine.InputSystem.LowLevel.InputEvent.html#UnityEngine_InputSystem_LowLevel_InputEvent_sizeInBytes)|Total size of the event in bytes.|
|
||||
|
||||
You can observe the events received for a specific input device in the [input debugger](Debugging.md#debugging-devices).
|
||||
|
||||
## Types of events
|
||||
|
||||
### State events
|
||||
|
||||
A state event contains the input state for a Device. The Input System uses these events to feed new input to Devices.
|
||||
|
||||
There are two types of state events:
|
||||
|
||||
* [`StateEvent`](../api/UnityEngine.InputSystem.LowLevel.StateEvent.html) (`'STAT'`)
|
||||
* [`DeltaStateEvent`](../api/UnityEngine.InputSystem.LowLevel.StateEvent.html) (`'DLTA'`)
|
||||
|
||||
[`StateEvent`](../api/UnityEngine.InputSystem.LowLevel.StateEvent.html) contains a full snapshot of the entire state of a Device in the format specific to that Device. The [`stateFormat`](../api/UnityEngine.InputSystem.LowLevel.StateEvent.html#UnityEngine_InputSystem_LowLevel_StateEvent_stateFormat) field identifies the type of the data in the event. You can access the raw data using the [`state`](../api/UnityEngine.InputSystem.LowLevel.StateEvent.html#UnityEngine_InputSystem_LowLevel_StateEvent_state) pointer and [`stateSizeInBytes`](../api/UnityEngine.InputSystem.LowLevel.StateEvent.html#UnityEngine_InputSystem_LowLevel_StateEvent_stateSizeInBytes).
|
||||
|
||||
A [`DeltaStateEvent`](../api/UnityEngine.InputSystem.LowLevel.DeltaStateEvent.html) is like a [`StateEvent`](../api/UnityEngine.InputSystem.LowLevel.StateEvent.html), but only contains a partial snapshot of the state of a Device. The Input System usually sends this for Devices that require a large state record, to reduce the amount of memory it needs to update if only some of the Controls change their state. To access the raw data, you can use the [`deltaState`](../api/UnityEngine.InputSystem.LowLevel.DeltaStateEvent.html#UnityEngine_InputSystem_LowLevel_DeltaStateEvent_deltaState) pointer and [`deltaStateSizeInBytes`](../api/UnityEngine.InputSystem.LowLevel.DeltaStateEvent.html#UnityEngine_InputSystem_LowLevel_DeltaStateEvent_deltaStateSizeInBytes). The Input System should apply the data to the Device's state at the offset defined by [`stateOffset`](../api/UnityEngine.InputSystem.LowLevel.DeltaStateEvent.html#UnityEngine_InputSystem_LowLevel_DeltaStateEvent_stateOffset).
|
||||
|
||||
### Device events
|
||||
|
||||
Device events indicate a change that is relevant to a Device as a whole. If you're interested in these events, it is usually more convenient to subscribe to the higher-level [`InputSystem.onDeviceChange`](../api/UnityEngine.InputSystem.InputSystem.html#UnityEngine_InputSystem_InputSystem_onDeviceChange) event rather then processing [`InputEvents`](../api/UnityEngine.InputSystem.LowLevel.InputEvent.html) yourself.
|
||||
|
||||
There are three types of Device events:
|
||||
|
||||
* [`DeviceRemoveEvent`](../api/UnityEngine.InputSystem.LowLevel.DeviceRemoveEvent.html) (`'DREM'`)
|
||||
* [`DeviceConfigurationEvent`](../api/UnityEngine.InputSystem.LowLevel.DeviceConfigurationEvent.html) (`'DCFG'`)
|
||||
* [`DeviceResetEvent`](../api/UnityEngine.InputSystem.LowLevel.DeviceResetEvent.html) (`'DRST'`)
|
||||
|
||||
`DeviceRemovedEvent` indicates that a Device has been removed or disconnected. To query the device that has been removed, you can use the common [`deviceId`](../api/UnityEngine.InputSystem.LowLevel.InputEvent.html#UnityEngine_InputSystem_LowLevel_InputEvent_deviceId) field. This event doesn't have any additional data.
|
||||
|
||||
`DeviceConfigurationEvent` indicates that the configuration of a Device has changed. The meaning of this is Device-specific. This might signal, for example, that the layout used by the keyboard has changed or that, on a console, a gamepad has changed which player ID(s) it is assigned to. You can query the changed device from the common [`deviceId`](../api/UnityEngine.InputSystem.LowLevel.InputEvent.html#UnityEngine_InputSystem_LowLevel_InputEvent_deviceId) field. This event doesn't have any additional data.
|
||||
|
||||
`DeviceResetEvent` indicates that a device should get reset. This will trigger [`InputSystem.ResetDevice`](../api/UnityEngine.InputSystem.InputSystem.html#UnityEngine_InputSystem_InputSystem_ResetDevice_UnityEngine_InputSystem_InputDevice_System_Boolean_) to be called on the Device.
|
||||
|
||||
### Text events
|
||||
|
||||
[Keyboard](Keyboard.md) devices send these events to handle text input. If you're interested in these events, it's usually more convenient to subscribe to the higher-level [callbacks on the Keyboard class](Keyboard.md#text-input) rather than processing [`InputEvents`](../api/UnityEngine.InputSystem.LowLevel.InputEvent.html) yourself.
|
||||
|
||||
There are two types of text events:
|
||||
|
||||
* [`TextEvent`](../api/UnityEngine.InputSystem.LowLevel.TextEvent.html) (`'TEXT'`)
|
||||
* [`IMECompositionEvent`](../api/UnityEngine.InputSystem.LowLevel.IMECompositionEvent.html) (`'IMES'`)
|
||||
|
||||
## Working with events
|
||||
|
||||
### Listening to events
|
||||
|
||||
If you want to do any monitoring or processing on incoming events yourself, subscribe to the [`InputSystem.onEvent`](../api/UnityEngine.InputSystem.InputSystem.html#UnityEngine_InputSystem_InputSystem_onEvent) callback.
|
||||
|
||||
```CSharp
|
||||
InputSystem.onEvent +=
|
||||
(eventPtr, device) =>
|
||||
{
|
||||
Debug.Log($"Received event for {device}");
|
||||
};
|
||||
```
|
||||
|
||||
An [`IObservable`](https://docs.microsoft.com/en-us/dotnet/api/system.iobservable-1) interface is provided to more conveniently process events.
|
||||
|
||||
```CSharp
|
||||
// Wait for first button press on a gamepad.
|
||||
InputSystem.onEvent
|
||||
.ForDevice<Gamepad>()
|
||||
.Where(e => e.HasButtonPress())
|
||||
.CallOnce(ctrl => Debug.Log($"Button {ctrl} pressed"));
|
||||
```
|
||||
|
||||
To enumerate the controls that have value changes in an event, you can use [`InputControlExtensions.EnumerateChangedControls`](../api/UnityEngine.InputSystem.InputControlExtensions.html#UnityEngine_InputSystem_InputControlExtensions_EnumerateChangedControls_UnityEngine_InputSystem_LowLevel_InputEventPtr_UnityEngine_InputSystem_InputDevice_System_Single_).
|
||||
|
||||
```CSharp
|
||||
InputSystem.onEvent
|
||||
.Call(eventPtr =>
|
||||
{
|
||||
foreach (var control in eventPtr.EnumerateChangedControls())
|
||||
Debug.Log($"Control {control} changed value to {control.ReadValueFromEventAsObject(eventPtr)}");
|
||||
};
|
||||
```
|
||||
|
||||
This is significantly more efficient than manually iterating over [`InputDevice.allControls`](../api/UnityEngine.InputSystem.InputDevice.html#UnityEngine_InputSystem_InputDevice_allControls) and reading out the value of each control from the event.
|
||||
|
||||
### Reading state events
|
||||
|
||||
State events contain raw memory snapshots for Devices. As such, interpreting the data in the event requires knowledge about where and how individual state is stored for a given Device.
|
||||
|
||||
The easiest way to access state contained in a state event is to rely on the Device that the state is meant for. You can ask any Control to read its value from a given event rather than from its own internally stored state.
|
||||
|
||||
For example, the following code demonstrates how to read a value for [`Gamepad.leftStick`](../api/UnityEngine.InputSystem.Gamepad.html#UnityEngine_InputSystem_Gamepad_leftStick) from a state event targeted at a [`Gamepad`](../api/UnityEngine.InputSystem.Gamepad.html).
|
||||
|
||||
```CSharp
|
||||
InputSystem.onEvent +=
|
||||
(eventPtr, device) =>
|
||||
{
|
||||
// Ignore anything that isn't a state event.
|
||||
if (!eventPtr.IsA<StateEvent>() && !eventPtr.IsA<DeltaStateEvent>())
|
||||
return;
|
||||
|
||||
var gamepad = device as Gamepad;
|
||||
if (gamepad == null)
|
||||
{
|
||||
// Event isn't for a gamepad or device ID is no longer valid.
|
||||
return;
|
||||
}
|
||||
|
||||
var leftStickValue = gamepad.leftStick.ReadValueFromEvent(eventPtr);
|
||||
};
|
||||
```
|
||||
|
||||
### Creating events
|
||||
|
||||
Anyone can create and queue new input events against any existing Device. Queueing an input event is thread-safe, which means that event generation can happen in background threads.
|
||||
|
||||
>__Note__: Unity allocates limited memory to events that come from background threads. If background threads produce too many events, queueing an event from a thread blocks the thread until the main thread flushes out the background event queue.
|
||||
|
||||
Note that queuing an event doesn't immediately consume the event. Event processing happens on the next update (depending on [`InputSettings.updateMode`](Settings.md#update-mode), it is triggered either manually via [`InputSystem.Update`](../api/UnityEngine.InputSystem.InputSystem.html#UnityEngine_InputSystem_InputSystem_Update), or automatically as part of the Player loop).
|
||||
|
||||
#### Sending state events
|
||||
|
||||
For Devices that have a corresponding "state struct" describing the state of the device, the easiest way of sending input to the Device is to simply queue instances of those structs:
|
||||
|
||||
```CSharp
|
||||
// Mouse.
|
||||
InputSystem.QueueStateEvent(Mouse.current, new MouseState { position = new Vector2(123, 234) });
|
||||
|
||||
// Keyboard.
|
||||
InputSystem.QueueStateEvent(Keyboard.current, new KeyboardState(Key.LeftCtrl, Key.A));
|
||||
```
|
||||
|
||||
`Touchscreen` is somewhat special in that it expects its input to be in [`TouchState`](../api/UnityEngine.InputSystem.LowLevel.TouchState.html) format.
|
||||
|
||||
```CSharp
|
||||
// Start touch.
|
||||
InputSystem.QueueStateEvent(Touchscreen.current,
|
||||
new TouchState { touchId = 1, phase = TouchPhase.Began, position = new Vector2(123, 234) });
|
||||
|
||||
// Move touch.
|
||||
InputSystem.QueueStateEvent(Touchscreen.current,
|
||||
new TouchState { touchId = 1, phase = TouchPhase.Moved, position = new Vector2(234, 345) });
|
||||
|
||||
// End touch.
|
||||
InputSystem.QueueStateEvent(Touchscreen.current,
|
||||
new TouchState { touchId = 1, phase = TouchPhase.Ended, position = new Vector2(123, 234) });
|
||||
```
|
||||
|
||||
>__IMPORTANT:__ [Touch IDs](../api/UnityEngine.InputSystem.Controls.TouchControl.html#UnityEngine_InputSystem_Controls_TouchControl_touchId) cannot be 0! A valid touch must have a non-zero touch ID. Concurrent touches must each have a unique ID. After a touch has ended, its ID can be reused – although it is recommended to not do so.
|
||||
|
||||
If the exact format of the state used by a given Device is not known, the easiest way to send input to it is to simply create a [`StateEvent`](../api/UnityEngine.InputSystem.LowLevel.StateEvent.html) from the Device itself:
|
||||
|
||||
```CSharp
|
||||
// `StateEvent.From` creates a temporary buffer in unmanaged memory that holds
|
||||
// a state event large enough for the given device and contains a memory
|
||||
// copy of the device's current state.
|
||||
InputEventPtr eventPtr;
|
||||
using (StateEvent.From(myDevice, out eventPtr))
|
||||
{
|
||||
((AxisControl) myDevice["myControl"]).WriteValueIntoEvent(0.5f, eventPtr);
|
||||
InputSystem.QueueEvent(eventPtr);
|
||||
}
|
||||
```
|
||||
|
||||
Alternatively, you can send events for individual Controls.
|
||||
|
||||
```CSharp
|
||||
// Send event to update leftStick on the gamepad.
|
||||
InputSystem.QueueDeltaStateEvent(Gamepad.current.leftStick,
|
||||
new Vector2(0.123f, 0.234f);
|
||||
```
|
||||
|
||||
Note that delta state events only work for Controls that are both byte-aligned and a multiple of 8 bits in size in memory. You can't send a delta state event for a button Control that is stored as a single bit, for example.
|
||||
|
||||
### Capturing Events
|
||||
|
||||
>NOTE: To download a sample project which contains a reusable MonoBehaviour called `InputRecorder`, which can capture and replay input from arbitrary devices, open the Package Manager, select the Input System Package, and choose the sample project "Input Recorder" to download.
|
||||
|
||||
You can use the [`InputEventTrace`](../api/UnityEngine.InputSystem.LowLevel.InputEventTrace.html) class to record input events for later processing:
|
||||
|
||||
```CSharp
|
||||
var trace = new InputEventTrace(); // Can also give device ID to only
|
||||
// trace events for a specific device.
|
||||
|
||||
trace.Enable();
|
||||
|
||||
//... run stuff
|
||||
|
||||
var current = new InputEventPtr();
|
||||
while (trace.GetNextEvent(ref current))
|
||||
{
|
||||
Debug.Log("Got some event: " + current);
|
||||
}
|
||||
|
||||
// Also supports IEnumerable.
|
||||
foreach (var eventPtr in trace)
|
||||
Debug.Log("Got some event: " + eventPtr);
|
||||
|
||||
// Trace consumes unmanaged resources. Make sure to dispose.
|
||||
trace.Dispose();
|
||||
```
|
||||
|
||||
Dispose event traces after use, so that they do not leak memory on the unmanaged (C++) memory heap.
|
||||
|
||||
You can also write event traces out to files/streams, load them back in, and replay recorded streams.
|
||||
|
||||
```CSharp
|
||||
// Set up a trace with such that it automatically grows in size as needed.
|
||||
var trace = new InputEventTrace(growBuffer: true);
|
||||
trace.Enable();
|
||||
|
||||
// ... capture some input ...
|
||||
|
||||
// Write trace to file.
|
||||
trace.WriteTo("mytrace.inputtrace.");
|
||||
|
||||
// Load trace from same file.
|
||||
var loadedTrace = InputEventTrace.LoadFrom("mytrace.inputtrace");
|
||||
```
|
||||
|
||||
You can replay captured traces directly from [`InputEventTrace`](../api/UnityEngine.InputSystem.LowLevel.InputEventTrace.html) instances using the [`Replay`](../api/UnityEngine.InputSystem.LowLevel.InputEventTrace.html#UnityEngine_InputSystem_LowLevel_InputEventTrace_Replay_) method.
|
||||
|
||||
```CSharp
|
||||
// The Replay method returns a ReplayController that can be used to
|
||||
// configure and control playback.
|
||||
var controller = trace.Replay();
|
||||
|
||||
// For example, to not replay the events as is but rather create new devices and send
|
||||
// the events to them, call WithAllDevicesMappedToNewInstances.
|
||||
controller.WithAllDevicessMappedToNewInstances();
|
||||
|
||||
// Replay all frames one by one.
|
||||
controller.PlayAllFramesOnyByOne();
|
||||
|
||||
// Replay events in a way that tries to simulate original event timing.
|
||||
controller.PlayAllEventsAccordingToTimestamps();
|
||||
```
|
||||
|
||||
## Processing events
|
||||
|
||||
[Events](../api/UnityEngine.InputSystem.LowLevel.InputEvent.html) are collected on a queue by the Unity runtime. This queue is regularly flushed out and the events on it processed. Events can be added to the queue manually by calling [`InputSystem.QueueEvent`](../api/UnityEngine.InputSystem.InputSystem.html#UnityEngine_InputSystem_InputSystem_QueueEvent_UnityEngine_InputSystem_LowLevel_InputEventPtr_).
|
||||
|
||||
Each time input is processed, [`InputSystem.Update`](../api/UnityEngine.InputSystem.InputSystem.html#UnityEngine_InputSystem_InputSystem_Update_) is called implicitly by the Unity runtime.
|
||||
|
||||
The interval at which this happens is determined by the ["Update Mode"](Settings.md#update-mode) configured in the settings. By default, input is processed in each frame __before__ <c>MonoBehaviour.Update</c> methods are called. If the setting is changed to process input in fixed updates, then this changes to input being processed each time before <c>MonoBehaviour.FixedUpdate</c> methods are called.
|
||||
|
||||
Normally, when input is processed, __all__ outstanding input events on the queue will be consumed. There are two exceptions to this, however.
|
||||
|
||||
When using [`UpdateMode.ProcessEventsInFixedUpdate`](../api/UnityEngine.InputSystem.InputSettings.UpdateMode.html#UnityEngine_InputSystem_InputSettings_UpdateMode_ProcessEventsInFixedUpdate), the Input System attempts to associate events with the timeslice of the corresponding <c>FixedUpdate</c>. This is based on the [timestamps](../api/UnityEngine.InputSystem.LowLevel.InputEvent.html#UnityEngine_InputSystem_LowLevel_InputEvent_time) of the events and a "best effort" at calculating the corresponding timeslice of the current <c>FixedUpdated</c>.
|
||||
|
||||
The other exception are [`BeforeRender`](../api/UnityEngine.InputSystem.LowLevel.InputUpdateType.html#UnityEngine_InputSystem_LowLevel_InputUpdateType_BeforeRender) updates. These updates are run after fixed or dynamic updates but before rendering and used used exclusively to update devices such as VR headsets that need the most up-to-date tracking data. Other input is not consumed from such updates and these updates are only enabled if such devices are actually present. `BeforeRender` updates are not considered separate frames as far as input is concerned.
|
||||
|
||||
>__Note__: Manually calling [`InputSystem.Update`](../api/UnityEngine.InputSystem.InputSystem.html#UnityEngine_InputSystem_InputSystem_Update_) is strongly advised against except within tests employing [`InputTestFixture`](../api/UnityEngine.InputSystem.InputTestFixture.html) or when explicitly setting the system to [manual update mode](../api/UnityEngine.InputSystem.InputSettings.UpdateMode.html#UnityEngine_InputSystem_InputSettings_UpdateMode_ProcessEventsManually).
|
||||
|
||||
Methods such as [`InputAction.WasPerformedThisFrame`](../api/UnityEngine.InputSystem.InputAction.html#UnityEngine_InputSystem_InputAction_WasPerformedThisFrame) and [`InputAction.WasPerformedThisFrame`](../api/UnityEngine.InputSystem.InputAction.html#UnityEngine_InputSystem_InputAction_WasPerformedThisFrame) operate implicitly based on the [`InputSystem.Update`] cadence described above. Meaning, that they refer to the state as per the __last__ fixed/dynamic/manual update happened.
|
||||
|
||||
You can query the [current/last update type](../api/UnityEngine.InputSystem.LowLevel.InputState.html#UnityEngine_InputSystem_LowLevel_InputState_currentUpdateType) and [count](../api/UnityEngine.InputSystem.LowLevel.InputState.html#UnityEngine_InputSystem_LowLevel_InputState_updateCount) from [`InputState`](../api/UnityEngine.InputSystem.LowLevel.InputState.html).
|
||||
|
||||
### Merging of events
|
||||
|
||||
Input system uses event mering to reduce amount of events required to be processed.
|
||||
This greatly improves performance when working with high refresh rate devices like 8000 Hz mice, touchscreens and others.
|
||||
|
||||
For example let's take a stream of 7 mouse events coming in the same update:
|
||||
|
||||
```
|
||||
|
||||
Mouse Mouse Mouse Mouse Mouse Mouse Mouse
|
||||
Event no1 Event no2 Event no3 Event no4 Event no5 Event no6 Event no7
|
||||
Time 1 Time 2 Time 3 Time 4 Time 5 Time 6 Time 7
|
||||
Pos(10,20) Pos(12,21) Pos(13,23) Pos(14,24) Pos(16,25) Pos(17,27) Pos(18,28)
|
||||
Delta(1,1) Delta(2,1) Delta(1,2) Delta(1,1) Delta(2,1) Delta(1,2) Delta(1,1)
|
||||
BtnLeft(0) BtnLeft(0) BtnLeft(0) BtnLeft(1) BtnLeft(1) BtnLeft(1) BtnLeft(1)
|
||||
```
|
||||
|
||||
To reduce workload we can skip events that are not encoding button state changes:
|
||||
|
||||
```
|
||||
Mouse Mouse Mouse
|
||||
Time 3 Time 4 Time 7
|
||||
Event no3 Event no4 Event no7
|
||||
Pos(13,23) Pos(14,24) Pos(18,28)
|
||||
Delta(3,3) Delta(1,1) Delta(4,4)
|
||||
BtnLeft(0) BtnLeft(1) BtnLeft(1)
|
||||
```
|
||||
|
||||
In that case we combine no1, no2, no3 together into no3 and accumulate the delta,
|
||||
then we keep no4 because it stores the transition from button unpressed to button pressed,
|
||||
and it's important to keep the exact timestamp of such transition.
|
||||
Later we combine no5, no6, no7 together into no7 because it is the last event in the update.
|
||||
|
||||
Currently this approach is implemented for:
|
||||
- `FastMouse`, combines events unless `buttons` or `clickCount` differ in `MouseState`.
|
||||
- `Touchscreen`, combines events unless `touchId`, `phaseId` or `flags` differ in `TouchState`.
|
||||
|
||||
You can disable merging of events by:
|
||||
```
|
||||
InputSystem.settings.disableRedundantEventsMerging = true;
|
||||
```
|
@@ -0,0 +1,317 @@
|
||||
---
|
||||
uid: input-system-hid
|
||||
---
|
||||
# HID Support
|
||||
|
||||
Human Interface Device (HID) is a [specification](https://www.usb.org/hid) to describe peripheral user input devices connected to computers via USB or Bluetooth. HID is commonly used to implement devices such as gamepads, joysticks, or racing wheels.
|
||||
|
||||
The Input System directly supports HID (connected via both USB and Bluetooth) on Windows, MacOS, and the Universal Windows Platform (UWP). The system might support HID on other platforms, but not deliver input through HID-specific APIs. For example, on Linux, the system supports gamepad and joystick HIDs through SDL, but doesn't support other HIDs.
|
||||
|
||||
Every HID comes with a device descriptor. To browse through the descriptor of an HID from the Input Debugger, click the __HID Descriptor__ button in the device debugger window. To specify the type of the device, the HID descriptor reports entry numbers in the [HID usage tables](https://www.usb.org/document-library/hid-usage-tables-112), and a list of all controls on the device, along with their data ranges and usages.
|
||||
|
||||

|
||||
|
||||
The Input System handles HIDs in one of two ways:
|
||||
|
||||
1. The system has a known layout for the specific HID.
|
||||
2. If the system does not have a known layout, it auto-generates one for the HID.
|
||||
|
||||
## Auto-generated layouts
|
||||
|
||||
By default, the Input System creates layouts and Device representations for any HID which reports its usage as `GenericDesktop/Joystick`, `GenericDesktop/Gamepad`, or `GenericDesktop/MultiAxisController` (see the [HID usage table specifications](https://www.usb.org/document-library/hid-usage-tables-112) for more information). To change the list of supported usages, set [`HIDSupport.supportedHIDUsages`](../api/UnityEngine.InputSystem.HID.HIDSupport.html#UnityEngine_InputSystem_HID_HIDSupport_supportedHIDUsages).
|
||||
|
||||
When the Input System automatically creates a layout for an HID, it always reports these Devices as [`Joysticks`](Joystick.md), represented by the [`Joystick` device class](../api/UnityEngine.InputSystem.Joystick.html). The first elements with a reported HID usage of `GenericDesktop/X` and `GenericDesktop/Y` together form the joystick's [`stick`](../api/UnityEngine.InputSystem.Joystick.html#UnityEngine_InputSystem_Joystick_stick) Control. The system then adds Controls for all further HID axis or button elements, using the Control names reported by the HID specification. The Input System assigns the first control with an HID usage of `Button/Button 1` to the joystick's [`trigger`](../api/UnityEngine.InputSystem.Joystick.html#UnityEngine_InputSystem_Joystick_trigger) Control.
|
||||
|
||||
The auto-generated layouts represent a "best effort" on the part of the Input System. The way Human Interface Devices describe themselves in accordance with the HID standard is too ambiguous in practice, so generated layouts might lead to Controls that don't work as expected. For example, while the layout builder can identify hat switches and D-pads, it can often only make guesses as to which direction represents which. The same goes for individual buttons, which generally aren't assigned any meaning in HID.
|
||||
|
||||
The best way to resolve the situation of HIDs not working as expected is to add a custom layout, which bypasses auto-generation altogether. See [Creating a custom device layout](#creating-a-custom-device-layout) for details.
|
||||
|
||||
## HID output
|
||||
|
||||
HIDs can support output (for example, to toggle lights or force feedback motors on a gamepad). Unity controls output by sending HID Output Report commands to a Device. Output reports use Device-specific data formats. To use HID Output Reports, call [`InputDevice.ExecuteCommand`](../api/UnityEngine.InputSystem.InputDevice.html#UnityEngine_InputSystem_InputDevice_ExecuteCommand__1___0__) to send a command struct with the [`typeStatic`](../api/UnityEngine.InputSystem.LowLevel.IInputDeviceCommandInfo.html#properties) property set as `"HIDO"` to a Device. The command struct contains the Device-specific data sent out to the HID.
|
||||
|
||||
## Creating a custom device layout
|
||||
|
||||
Often, when using the layouts auto-generated for HIDs, the result isn't ideal. Controls don't receive proper names specific to the Device, some Controls might not work as expected, and some Controls that use vendor-specific formats might not appear altogether.
|
||||
|
||||
The best way to deal with this is to override the HID fallback and set up a custom Device layout specifically for your Device. This overrides the default auto-generation and gives you full control over how the Device is exposed.
|
||||
|
||||
Below are three example workflows showing different ways to achieve this.
|
||||
|
||||
- [Example 1 - Use an existing C# InputDevice](#custom-device-workflow-example-1---use-an-existing-c-inputdevice)
|
||||
- [Example 2 - Create your own InputDevice class](#custom-device-workflow-example-2---create-your-own-inputdevice-class)
|
||||
- [Example 3 - A more complex example using the PS4 DualShock Controller](#custom-device-workflow-example-3---ps4-dualshock-controller)
|
||||
|
||||
### Custom Device Workflow Example 1 - Use an existing C# InputDevice
|
||||
|
||||
If you want to use one of the existing C# [`InputDevice`](../api/UnityEngine.InputSystem.InputDevice.html) classes in code to interface with your Device, you can build on an existing layout using JSON:
|
||||
|
||||
```
|
||||
{
|
||||
"name" : "MyDevice",
|
||||
"extend" : "Gamepad", // Or some other thing
|
||||
"controls" : [
|
||||
{
|
||||
"name" : "firstButton",
|
||||
"layout" : "Button",
|
||||
"offset" : 0,
|
||||
"bit": 0,
|
||||
"format" : "BIT",
|
||||
},
|
||||
{
|
||||
"name" : "secondButton",
|
||||
"layout" : "Button",
|
||||
"offset" : 0,
|
||||
"bit": 1,
|
||||
"format" : "BIT",
|
||||
},
|
||||
{
|
||||
"name" : "axis",
|
||||
"layout" : "Axis",
|
||||
"offset" : 4,
|
||||
"format" : "FLT",
|
||||
"parameters" : "clamp=true,clampMin=0,clampMax=1"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
You then register your layout with the system and then instantiate it:
|
||||
|
||||
```C#
|
||||
InputSystem.RegisterControlLayout(myDeviceJson);
|
||||
var device = InputSystem.AddDevice("MyDevice");
|
||||
```
|
||||
|
||||
### Custom Device Workflow Example 2 - Create your own InputDevice class
|
||||
|
||||
Alternatively, you can create your own [`InputDevice`](../api/UnityEngine.InputSystem.InputDevice.html) class and state layouts in C#.
|
||||
|
||||
```C#
|
||||
public struct MyDeviceState : IInputStateTypeInfo
|
||||
{
|
||||
// FourCC type codes are used to identify the memory layouts of state blocks.
|
||||
public FourCC format => new FourCC('M', 'D', 'E', 'V');
|
||||
|
||||
[InputControl(name = "firstButton", layout = "Button", bit = 0)]
|
||||
[InputControl(name = "secondButton", layout = "Button", bit = 1)]
|
||||
public int buttons;
|
||||
[InputControl(layout = "Analog", parameters="clamp=true,clampMin=0,clampMax=1")]
|
||||
public float axis;
|
||||
}
|
||||
|
||||
[InputState(typeof(MyDeviceState)]
|
||||
public class MyDevice : InputDevice
|
||||
{
|
||||
public ButtonControl firstButton { get; private set; }
|
||||
public ButtonControl secondButton { get; private set; }
|
||||
public AxisControl axis { get; private set; }
|
||||
|
||||
protected override void FinishSetup(InputControlSetup setup)
|
||||
{
|
||||
firstButton = setup.GetControl<ButtonControl>(this, "firstButton");
|
||||
secondButton = setup.GetControl<ButtonControl>(this, "secondButton");
|
||||
axis = setup.GetControl<AxisControl>(this, "axis");
|
||||
base.FinishSetup(setup);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
To create an instance of your Device, register it as a layout and then instantiate it:
|
||||
|
||||
```C#
|
||||
InputSystem.RegisterControlLayout("MyDevice", typeof(MyDevice));
|
||||
InputSystem.AddDevice("MyDevice");
|
||||
```
|
||||
|
||||
### Custom Device Workflow Example 3 - PS4 DualShock Controller
|
||||
|
||||
This example workflow uses the same technique as the previous example, but provides more detail by using the PS4 DualShock controller as a more complex device to set up.
|
||||
|
||||
The following example assumes that the Input System doesn't already have a custom layout for the PS4 DualShock controller, and that you want to add such a layout.
|
||||
|
||||
In this example, you want to expose the controller as a [`Gamepad`](Gamepad.md) and you roughly know the HID data format used by the Device.
|
||||
|
||||
>__Tip__: If you don't know the format of a given HID you want to support, you can open the Input Debugger with the Device plugged in and pop up both the debugger view for the Device and the window showing the HID descriptor. Then, you can go through the Controls one by one, see what happens in the debug view, and correlate that to the Controls in the HID descriptor. You can also double-click individual events and compare the raw data coming in from the Device. If you select two events in the event trace, you can then right-click them and choose __Compare__ to open a window that shows only the differences between the two events.
|
||||
|
||||
#### Step 1: The state struct
|
||||
|
||||
The first step is to describe in detail what format that input data for the Device comes in, as well as the [`InputControl`](../api/UnityEngine.InputSystem.InputControl.html) instances that should read out individual pieces of information from that data.
|
||||
|
||||
The HID input reports from the PS4 controller look approximately like this:
|
||||
|
||||
```C++
|
||||
struct PS4InputReport
|
||||
{
|
||||
byte reportId; // #0
|
||||
byte leftStickX; // #1
|
||||
byte leftStickY; // #2
|
||||
byte rightStickX; // #3
|
||||
byte rightStickY; // #4
|
||||
byte dpad : 4; // #5 bit #0 (0=up, 2=right, 4=down, 6=left)
|
||||
byte squareButton : 1; // #5 bit #4
|
||||
byte crossButton : 1; // #5 bit #5
|
||||
byte circleButton : 1; // #5 bit #6
|
||||
byte triangleButton : 1; // #5 bit #7
|
||||
byte leftShoulder : 1; // #6 bit #0
|
||||
byte rightShoulder : 1; // #6 bit #1
|
||||
byte leftTriggerButton : 2;// #6 bit #2
|
||||
byte rightTriggerButton : 2;// #6 bit #3
|
||||
byte shareButton : 1; // #6 bit #4
|
||||
byte optionsButton : 1; // #6 bit #5
|
||||
byte leftStickPress : 1; // #6 bit #6
|
||||
byte rightStickPress : 1; // #6 bit #7
|
||||
byte psButton : 1; // #7 bit #0
|
||||
byte touchpadPress : 1; // #7 bit #1
|
||||
byte padding : 6;
|
||||
byte leftTrigger; // #8
|
||||
byte rightTrigger; // #9
|
||||
}
|
||||
```
|
||||
|
||||
You can translate this into a C# struct:
|
||||
|
||||
```CSharp
|
||||
// We receive data as raw HID input reports. This struct
|
||||
// describes the raw binary format of such a report.
|
||||
[StructLayout(LayoutKind.Explicit, Size = 32)]
|
||||
struct DualShock4HIDInputReport : IInputStateTypeInfo
|
||||
{
|
||||
// Because all HID input reports are tagged with the 'HID ' FourCC,
|
||||
// this is the format we need to use for this state struct.
|
||||
public FourCC format => new FourCC('H', 'I', 'D');
|
||||
|
||||
// HID input reports can start with an 8-bit report ID. It depends on the device
|
||||
// whether this is present or not. On the PS4 DualShock controller, it is
|
||||
// present. We don't really need to add the field, but let's do so for the sake of
|
||||
// completeness. This can also help with debugging.
|
||||
[FieldOffset(0)] public byte reportId;
|
||||
|
||||
// The InputControl annotations here probably look a little scary, but what we do
|
||||
// here is relatively straightforward. The fields we add we annotate with
|
||||
// [FieldOffset] to force them to the right location, and then we add InputControl
|
||||
// to attach controls to the fields. Each InputControl attribute can only do one of
|
||||
// two things: either it adds a new control or it modifies an existing control.
|
||||
// Given that our layout is based on Gamepad, almost all the controls here are
|
||||
// inherited from Gamepad, and we just modify settings on them.
|
||||
|
||||
[InputControl(name = "leftStick", layout = "Stick", format = "VC2B")]
|
||||
[InputControl(name = "leftStick/x", offset = 0, format = "BYTE",
|
||||
parameters = "normalize,normalizeMin=0,normalizeMax=1,normalizeZero=0.5")]
|
||||
[InputControl(name = "leftStick/left", offset = 0, format = "BYTE",
|
||||
parameters = "normalize,normalizeMin=0,normalizeMax=1,normalizeZero=0.5,clamp,clampMin=0,clampMax=0.5,invert")]
|
||||
[InputControl(name = "leftStick/right", offset = 0, format = "BYTE",
|
||||
parameters = "normalize,normalizeMin=0,normalizeMax=1,normalizeZero=0.5,clamp,clampMin=0.5,clampMax=1")]
|
||||
[InputControl(name = "leftStick/y", offset = 1, format = "BYTE",
|
||||
parameters = "invert,normalize,normalizeMin=0,normalizeMax=1,normalizeZero=0.5")]
|
||||
[InputControl(name = "leftStick/up", offset = 1, format = "BYTE",
|
||||
parameters = "normalize,normalizeMin=0,normalizeMax=1,normalizeZero=0.5,clamp,clampMin=0,clampMax=0.5,invert")]
|
||||
[InputControl(name = "leftStick/down", offset = 1, format = "BYTE",
|
||||
parameters = "normalize,normalizeMin=0,normalizeMax=1,normalizeZero=0.5,clamp,clampMin=0.5,clampMax=1,invert=false")]
|
||||
[FieldOffset(1)] public byte leftStickX;
|
||||
[FieldOffset(2)] public byte leftStickY;
|
||||
|
||||
[InputControl(name = "rightStick", layout = "Stick", format = "VC2B")]
|
||||
[InputControl(name = "rightStick/x", offset = 0, format = "BYTE", parameters = "normalize,normalizeMin=0,normalizeMax=1,normalizeZero=0.5")]
|
||||
[InputControl(name = "rightStick/left", offset = 0, format = "BYTE", parameters = "normalize,normalizeMin=0,normalizeMax=1,normalizeZero=0.5,clamp,clampMin=0,clampMax=0.5,invert")]
|
||||
[InputControl(name = "rightStick/right", offset = 0, format = "BYTE", parameters = "normalize,normalizeMin=0,normalizeMax=1,normalizeZero=0.5,clamp,clampMin=0.5,clampMax=1")]
|
||||
[InputControl(name = "rightStick/y", offset = 1, format = "BYTE", parameters = "invert,normalize,normalizeMin=0,normalizeMax=1,normalizeZero=0.5")]
|
||||
[InputControl(name = "rightStick/up", offset = 1, format = "BYTE", parameters = "normalize,normalizeMin=0,normalizeMax=1,normalizeZero=0.5,clamp,clampMin=0,clampMax=0.5,invert")]
|
||||
[InputControl(name = "rightStick/down", offset = 1, format = "BYTE", parameters = "normalize,normalizeMin=0,normalizeMax=1,normalizeZero=0.5,clamp,clampMin=0.5,clampMax=1,invert=false")]
|
||||
[FieldOffset(3)] public byte rightStickX;
|
||||
[FieldOffset(4)] public byte rightStickY;
|
||||
|
||||
[InputControl(name = "dpad", format = "BIT", layout = "Dpad", sizeInBits = 4, defaultState = 8)]
|
||||
[InputControl(name = "dpad/up", format = "BIT", layout = "DiscreteButton", parameters = "minValue=7,maxValue=1,nullValue=8,wrapAtValue=7", bit = 0, sizeInBits = 4)]
|
||||
[InputControl(name = "dpad/right", format = "BIT", layout = "DiscreteButton", parameters = "minValue=1,maxValue=3", bit = 0, sizeInBits = 4)]
|
||||
[InputControl(name = "dpad/down", format = "BIT", layout = "DiscreteButton", parameters = "minValue=3,maxValue=5", bit = 0, sizeInBits = 4)]
|
||||
[InputControl(name = "dpad/left", format = "BIT", layout = "DiscreteButton", parameters = "minValue=5, maxValue=7", bit = 0, sizeInBits = 4)]
|
||||
[InputControl(name = "buttonWest", displayName = "Square", bit = 4)]
|
||||
[InputControl(name = "buttonSouth", displayName = "Cross", bit = 5)]
|
||||
[InputControl(name = "buttonEast", displayName = "Circle", bit = 6)]
|
||||
[InputControl(name = "buttonNorth", displayName = "Triangle", bit = 7)]
|
||||
[FieldOffset(5)] public byte buttons1;
|
||||
|
||||
[InputControl(name = "leftShoulder", bit = 0)]
|
||||
[InputControl(name = "rightShoulder", bit = 1)]
|
||||
[InputControl(name = "leftTriggerButton", layout = "Button", bit = 2)]
|
||||
[InputControl(name = "rightTriggerButton", layout = "Button", bit = 3)]
|
||||
[InputControl(name = "select", displayName = "Share", bit = 4)]
|
||||
[InputControl(name = "start", displayName = "Options", bit = 5)]
|
||||
[InputControl(name = "leftStickPress", bit = 6)]
|
||||
[InputControl(name = "rightStickPress", bit = 7)]
|
||||
[FieldOffset(6)] public byte buttons2;
|
||||
|
||||
[InputControl(name = "systemButton", layout = "Button", displayName = "System", bit = 0)]
|
||||
[InputControl(name = "touchpadButton", layout = "Button", displayName = "Touchpad Press", bit = 1)]
|
||||
[FieldOffset(7)] public byte buttons3;
|
||||
|
||||
[InputControl(name = "leftTrigger", format = "BYTE")]
|
||||
[FieldOffset(8)] public byte leftTrigger;
|
||||
|
||||
[InputControl(name = "rightTrigger", format = "BYTE")]
|
||||
[FieldOffset(9)] public byte rightTrigger;
|
||||
|
||||
[FieldOffset(30)] public byte batteryLevel;
|
||||
}
|
||||
```
|
||||
|
||||
#### Step 2: The InputDevice
|
||||
|
||||
Next, you need an `InputDevice` to represent your device. Because you're dealing with a gamepad, you must create a new subclass of `Gamepad`.
|
||||
|
||||
For simplicity, this example ignores the fact that there is a `DualShockGamepad` class that the actual `DualShockGamepadHID` is based on.
|
||||
|
||||
```CSharp
|
||||
// Using InputControlLayoutAttribute, we tell the system about the state
|
||||
// struct we created, which includes where to find all the InputControl
|
||||
// attributes that we placed on there. This is how the Input System knows
|
||||
// what controls to create and how to configure them.
|
||||
[InputControlLayout(stateType = typeof(DualShock4HIDInputReport)]
|
||||
public DualShock4GamepadHID : Gamepad
|
||||
{
|
||||
}
|
||||
```
|
||||
|
||||
#### Step 3: Registering the Device
|
||||
|
||||
The last step is to register your new type of Device and set up the Input System so that when a PS4 controller is connected, the Input System generates your custom Device instead of using the default HID fallback.
|
||||
|
||||
This only requires a call to [`InputSystem.RegisterLayout<T>`](../api/UnityEngine.InputSystem.InputSystem.html#UnityEngine_InputSystem_InputSystem_RegisterLayout__1_System_String_System_Nullable_UnityEngine_InputSystem_Layouts_InputDeviceMatcher__), giving it an [`InputDeviceMatcher`](../api/UnityEngine.InputSystem.Layouts.InputDeviceMatcher.html) that matches the description for a PS4 DualShock HID. In theory, you can place this call anywhere, but the best point for registering layouts is generally during startup. Doing so ensures that your custom layout is visible to the Unity Editor and therefore exposed, for example, in the Input Control picker.
|
||||
|
||||
You can insert your registration into the startup sequence by modifying the code for your `DualShock4GamepadHID` Device as follows:
|
||||
|
||||
```CSharp
|
||||
[InputControlLayout(stateType = typeof(DualShock4HIDInputReport)]
|
||||
#if UNITY_EDITOR
|
||||
[InitializeOnLoad] // Make sure static constructor is called during startup.
|
||||
#endif
|
||||
public DualShock4GamepadHID : Gamepad
|
||||
{
|
||||
static DualShock4GamepadHID()
|
||||
{
|
||||
// This is one way to match the Device.
|
||||
InputSystem.RegisterLayout<DualShock4GamepadHID>(
|
||||
new InputDeviceMatcher()
|
||||
.WithInterface("HID")
|
||||
.WithManufacturer("Sony.+Entertainment")
|
||||
.WithProduct("Wireless Controller"));
|
||||
|
||||
// Alternatively, you can also match by PID and VID, which is generally
|
||||
// more reliable for HIDs.
|
||||
InputSystem.RegisterLayout<DualShock4GamepadHID>(
|
||||
matches: new InputDeviceMatcher()
|
||||
.WithInterface("HID")
|
||||
.WithCapability("vendorId", 0x54C) // Sony Entertainment.
|
||||
.WithCapability("productId", 0x9CC)); // Wireless controller.
|
||||
}
|
||||
|
||||
// In the Player, to trigger the calling of the static constructor,
|
||||
// create an empty method annotated with RuntimeInitializeOnLoadMethod.
|
||||
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
|
||||
static void Init() {}
|
||||
}
|
||||
```
|
||||
|
||||
Your custom layout now picks up any Device that matches the manufacturer and product name strings, or the vendor and product IDs in its HID descriptor. The Input System now represents a `DualShock4GamepadHID` Device instance.
|
||||
|
||||
For more information, you can also read the [Device matching](Devices.md#matching) documentation.
|
@@ -0,0 +1,56 @@
|
||||
---
|
||||
uid: input-system-how-do-i
|
||||
---
|
||||
# How do I…?
|
||||
|
||||
A collection of frequently asked questions, and where to find their answers in the documentation.
|
||||
|
||||
> **Note:**
|
||||
>
|
||||
> If you're new to the Input System and have landed on this page looking for documentation, it's best to read the [QuickStart Guide](QuickStartGuide.md), and the [Concepts](Concepts.md) and [Workflows](Workflows.md) pages, so that you can make sure you're choosing the best workflow for your project's input requirements.
|
||||
>
|
||||
> This is because there are a number of different ways to read input using the Input System, and many of the answers on this page give you the quickest but least flexible solution, and may not be suitable for a project with more complex requirements.
|
||||
|
||||
|
||||
How do I...?
|
||||
|
||||
- [check if a specific key or button was pressed this frame?](../api/UnityEngine.InputSystem.Controls.ButtonControl.html#UnityEngine_InputSystem_Controls_ButtonControl_wasPressedThisFrame)
|
||||
|
||||
- [check if any key or button was pressed](../api/UnityEngine.InputSystem.InputSystem.html#UnityEngine_InputSystem_InputSystem_onAnyButtonPress)
|
||||
|
||||
- [find all connected gamepads?](../api/UnityEngine.InputSystem.Gamepad.html#UnityEngine_InputSystem_Gamepad_all)
|
||||
|
||||
- [find the gamepad that the player is currently using?](../api/UnityEngine.InputSystem.Gamepad.html#UnityEngine_InputSystem_Gamepad_current)
|
||||
|
||||
- [know when a new device was plugged in?](Devices.md#monitoring-devices)
|
||||
|
||||
- [create my own custom devices?](HID.md#creating-a-custom-device-layout)
|
||||
|
||||
- create a simple "Fire" type action?</br>
|
||||
Use the same techniques shown for the "Jump" action in the [Workflows section](Workflows.md)
|
||||
|
||||
- [require a button to be held down for some duration before triggering an action?](Interactions.html#hold)
|
||||
|
||||
- [use a "positive" and a "negative" button to drive an axis?](ActionBindings.html#1d-axis)
|
||||
|
||||
- [create a UI to rebind input in my game?](../api/UnityEngine.InputSystem.InputActionRebindingExtensions.html)
|
||||
|
||||
- [set up an Action to specifically target the left-hand XR controller?](../api/UnityEngine.InputSystem.XR.XRController.html#UnityEngine_InputSystem_XR_XRController_leftHand)
|
||||
|
||||
- [make my left-hand XR controller my right-hand one?](../api/UnityEngine.InputSystem.XR.XRController.html#UnityEngine_InputSystem_XR_XRController_leftHand)
|
||||
|
||||
- [get all current touches from the touchscreen?](Touch.md#reading-all-touches)
|
||||
|
||||
- [deal with my gamepad data arriving in a format different from `GamepadState`?](../api/UnityEngine.InputSystem.LowLevel.GamepadState.html)
|
||||
|
||||
- [force the Input System to use my own layout when the native backend discovers a specific Device?](Devices.md#native-devices)
|
||||
|
||||
- [add deadzoning to my gamepad sticks?](Gamepad.md#deadzones)
|
||||
|
||||
- [give my head tracking an extra update before rendering?](../api/UnityEngine.InputSystem.XR.XRHMD.html)
|
||||
|
||||
- [record events flowing through the system?](Debugging.md#other-tips)
|
||||
|
||||
- [see events as they're processed?](Debugging.md#other-tips)
|
||||
|
||||
- [see what Devices I have and what state they're in?](Debugging.html#debugging-devices)
|
After Width: | Height: | Size: 33 KiB |
After Width: | Height: | Size: 51 KiB |
After Width: | Height: | Size: 57 KiB |
After Width: | Height: | Size: 23 KiB |
After Width: | Height: | Size: 41 KiB |
After Width: | Height: | Size: 26 KiB |
After Width: | Height: | Size: 39 KiB |
After Width: | Height: | Size: 42 KiB |
After Width: | Height: | Size: 125 KiB |
After Width: | Height: | Size: 18 KiB |
After Width: | Height: | Size: 40 KiB |
After Width: | Height: | Size: 32 KiB |
After Width: | Height: | Size: 21 KiB |
After Width: | Height: | Size: 16 KiB |
After Width: | Height: | Size: 82 KiB |
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 309 KiB |
After Width: | Height: | Size: 33 KiB |
After Width: | Height: | Size: 40 KiB |
After Width: | Height: | Size: 30 KiB |
After Width: | Height: | Size: 43 KiB |
After Width: | Height: | Size: 76 KiB |
After Width: | Height: | Size: 17 KiB |
After Width: | Height: | Size: 21 KiB |
After Width: | Height: | Size: 52 KiB |
After Width: | Height: | Size: 436 KiB |
After Width: | Height: | Size: 63 KiB |
After Width: | Height: | Size: 39 KiB |
After Width: | Height: | Size: 20 KiB |
After Width: | Height: | Size: 286 KiB |