From 88dff4c25ea395e98058b0a1b3664f00d2862038 Mon Sep 17 00:00:00 2001 From: sue-arkin Date: Wed, 15 Jul 2026 13:07:04 +0100 Subject: [PATCH 1/7] Replacing diagrams --- .../Documentation~/Architecture.md | 152 +++++++++++++++++- 1 file changed, 150 insertions(+), 2 deletions(-) diff --git a/Packages/com.unity.inputsystem/Documentation~/Architecture.md b/Packages/com.unity.inputsystem/Documentation~/Architecture.md index a4530721a6..6eb8fc2089 100644 --- a/Packages/com.unity.inputsystem/Documentation~/Architecture.md +++ b/Packages/com.unity.inputsystem/Documentation~/Architecture.md @@ -15,7 +15,76 @@ The Input System can also send data back to the native backend in the form of [c # Input System (low-level) -![Low-Level Architecture](Images/InputArchitectureLowLevel.png) +The diagram below reads top-to-bottom as a layered pipeline: the native **platform backends** at the bottom feed the **InputManager**, which uses **layouts** to build **devices** whose state is stored in **Input State Memory** at the top. + +```mermaid +flowchart TB + %% ---------- Input State Memory (top) ---------- + StateMemory["Input State Memory + (unmanaged raw memory — each device and control + gets a chunk that stores its current state)"] + + %% ---------- Devices (built from layouts) ---------- + Gamepad_D["Gamepad (device)"] --> leftStick + leftStick --> x & y & up & down & left & right + Keyboard_D["Keyboard (device)"] --> a & b & c & d + leftStick -->|"state written to"| StateMemory + Keyboard_D -->|"state written to"| StateMemory + + %% ---------- Layouts (describe how to build controls and devices) ---------- + Mouse -->|derives| Pointer + Pen -->|derives| Pointer + Touchscreen -->|derives| Pointer + DS_PS4["DualShock (PS4)"] --> DualShock + DS_HID["DualShock (HID)"] --> DualShock + DualShock --> Gamepad_L["Gamepad (layout)"] + Keyboard_L["Keyboard (layout)"] + Stick(("Stick")) + Axis(("Axis")) + Button(("Button")) + Dpad(("Dpad")) + + %% Layout building blocks build the individual device controls + Gamepad_L -.->|builds| Gamepad_D + Stick -.->|builds| leftStick + Axis -.->|builds| x & y + Button -.->|builds| up & down & left & right + Keyboard_L -.->|builds| Keyboard_D + + %% ---------- InputManager (middle) ---------- + InputManager(["InputManager + Matches layouts to devices (InputDeviceMatcher), + builds devices (InputDeviceBuilder), creates & updates them"]) + Gamepad_L -->|"searched by"| InputManager + InputManager -->|"creates & updates"| Gamepad_D + InputManager -->|"creates & updates"| Keyboard_D + + %% ---------- Input Runtime (bottom) ---------- + DDQ["Device Discovery Queue"] + EQ["Event Queue"] + BEQ["Background Event Queue + (async; flushes into the foreground queue)"] + Backends["Platform Backends + Windows · macOS · Linux · UWP · iOS · Android + · Switch · Xbox · PS4 · WebGL · XR"] + Backends --> DDQ & EQ & BEQ + DDQ -->|"Device Discovered"| InputManager + EQ -->|"Update (flushes event buffers)"| InputManager + InputManager -->|"Queue Event"| EQ + InputManager -->|"Device Command (IOCTL-style)"| Backends + + %% ---------- Grouping by color ---------- + classDef layout fill:#e6f0ff,stroke:#4a78c0,color:#000; + classDef device fill:#e8f7e8,stroke:#4aa04a,color:#000; + classDef runtime fill:#fdf3d0,stroke:#b9962e,color:#000; + classDef mem fill:#f0e6f6,stroke:#8a5ea0,color:#000; + classDef manager fill:#ffffff,stroke:#e0403f,stroke-width:2px,color:#000; + class Mouse,Pen,Touchscreen,Pointer,DS_PS4,DS_HID,DualShock,Gamepad_L,Keyboard_L,Stick,Axis,Button,Dpad layout; + class Gamepad_D,leftStick,x,y,up,down,left,right,Keyboard_D,a,b,c,d device; + class DDQ,EQ,BEQ,Backends runtime; + class StateMemory mem; + class InputManager manager; +``` The low-level Input System code processes and interprets the memory from the event stream that the native backend provides, and dispatches individual events. @@ -25,7 +94,86 @@ The low-level system code also contains structs which describe the data layout o # Input System (high-level) -![High-Level Architecture](Images/InputArchitectureHighLevel.png) +The high-level system is easiest to understand in two parts: how input flows through the system at **runtime**, and how Actions are **authored as assets**. Both are shown below for a single player; each additional player gets its own `InputActionState` and a cloned `InputActionAsset` with its own device list and binding mask. + +**Runtime data flow** — a Device control's state is written into Input State memory, a State Change Monitor notices the change, the `InputActionState` is updated, and the resulting Action fires a callback on the `PlayerInput` component in the scene: + +```mermaid +flowchart LR + %% ---------- Devices ---------- + Keyboard["Keyboard"] --> space["space"] + + %% ---------- Input State (unmanaged raw memory) ---------- + KBbit["KeyboardState + 1 Bit for Space Key"] + space -->|"stored in"| KBbit + + %% ---------- Runtime ---------- + StateEvent["StateEvent (KeyboardState) + NativeInputSystem.onUpdate"] -->|feeds| OnUpdate["InputManager.OnUpdate()"] + + %% ---------- Action state ---------- + AState(["InputActionState + NotifyControlStateChanged()"]) + trig["triggerStates[]"] + bind["bindingStates[]"] + ctrl["controls[]"] + AState --> trig & bind & ctrl + OnUpdate ==>|"NotifyControlStateChanged()"| AState + KBbit -->|"State Change Monitor"| bind + space -->|"State Change Monitor"| ctrl + + %% ---------- Callback out to the scene ---------- + trig -->|triggers| IU["InputUser"] + IU -->|"OnActionTriggered()"| PI["PlayerInput + (Scene GameObject)"] + + classDef device fill:#e6f0ff,stroke:#4a78c0,color:#000; + classDef state fill:#cfcfcf,stroke:#555,color:#000; + classDef astate fill:#efe9ff,stroke:#7a5ec0,color:#000; + classDef runtime fill:#fdf3d0,stroke:#b9962e,color:#000; + classDef go fill:#d9d9d9,stroke:#666,color:#000; + class Keyboard,space device; + class KBbit state; + class AState,trig,bind,ctrl astate; + class StateEvent,OnUpdate runtime; + class IU,PI go; +``` + +**Asset structure** — an `InputActionAsset` contains Maps, Actions, and Bindings. At runtime these populate the arrays inside the `InputActionState` shown above (`m_State`): + +```mermaid +flowchart LR + %% ---------- Asset hierarchy ---------- + Asset["InputActionAsset: MyGame.inputactions + devices = [ Keyboard ] + bindingMask = { groups: KeyboardMouse }"] + Map["InputActionMap: gameplay"] + Act["InputAction (m_Actions[]) + gameplay/jump"] + Bind_a["InputBinding (m_Bindings[]) + path: <Keyboard>/space + action: jump — groups: KeyboardMouse"] + Bind_b["InputBinding (m_Bindings[]) + path: <Gamepad>/buttonSouth + action: jump — groups: Gamepad"] + Asset --> Map + Map --> Act + Map --> Bind_a & Bind_b + + %% ---------- Populates the runtime action state ---------- + Act -.->|populates| trig["triggerStates[]"] + Bind_a -.->|populates| bind["bindingStates[]"] + Bind_b -.->|populates| bind + bind -.->|resolves controls| ctrl["controls[]"] + State(["InputActionState + (m_State)"]) --- trig & bind & ctrl + + classDef asset fill:#e8f7e8,stroke:#4aa04a,color:#000; + classDef astate fill:#efe9ff,stroke:#7a5ec0,color:#000; + class Asset,Map,Act,Bind_a,Bind_b asset; + class trig,bind,ctrl,State astate; +``` 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-specification.md). From 242212a827ec81e766bf76ceeae0d26781a0bc4c Mon Sep 17 00:00:00 2001 From: sue-arkin Date: Wed, 15 Jul 2026 13:19:33 +0100 Subject: [PATCH 2/7] Updating text --- .../Documentation~/Architecture.md | 25 ++++++++++++++++--- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/Packages/com.unity.inputsystem/Documentation~/Architecture.md b/Packages/com.unity.inputsystem/Documentation~/Architecture.md index 6eb8fc2089..cc6a7cc6b4 100644 --- a/Packages/com.unity.inputsystem/Documentation~/Architecture.md +++ b/Packages/com.unity.inputsystem/Documentation~/Architecture.md @@ -15,7 +15,11 @@ The Input System can also send data back to the native backend in the form of [c # Input System (low-level) -The diagram below reads top-to-bottom as a layered pipeline: the native **platform backends** at the bottom feed the **InputManager**, which uses **layouts** to build **devices** whose state is stored in **Input State Memory** at the top. +The diagram of the low-level Input System reads top-to-bottom as a layered pipeline: + +1. The native platform backends at the bottom feed the InputManager. +1. The InputManager uses layouts to build devices. +1. The device's state is stored in Input State Memory at the top. ```mermaid flowchart TB @@ -94,9 +98,19 @@ The low-level system code also contains structs which describe the data layout o # Input System (high-level) -The high-level system is easiest to understand in two parts: how input flows through the system at **runtime**, and how Actions are **authored as assets**. Both are shown below for a single player; each additional player gets its own `InputActionState` and a cloned `InputActionAsset` with its own device list and binding mask. +The high-level system is easiest to understand in two parts: + +- How input flows through the system at runtime. +- How actions are authored as assets. + +The diagram shows both parts for a single player; each additional player gets its own `InputActionState` and a cloned `InputActionAsset` with its own device list and binding mask. -**Runtime data flow** — a Device control's state is written into Input State memory, a State Change Monitor notices the change, the `InputActionState` is updated, and the resulting Action fires a callback on the `PlayerInput` component in the scene: +The first diagram is for the runtime data flow: + +1. A device's control state is written into Input State memory. +1. A State Change Monitor notices the change. +1. The `InputActionState` is updated. +1. The resulting action fires a callback on the `PlayerInput` component in the scene. ```mermaid flowchart LR @@ -140,7 +154,10 @@ flowchart LR class IU,PI go; ``` -**Asset structure** — an `InputActionAsset` contains Maps, Actions, and Bindings. At runtime these populate the arrays inside the `InputActionState` shown above (`m_State`): +The second diagram is for the asset structure: + +1. An `InputActionAsset` contains maps, actions, and bindings. +1. At runtime these populate the arrays inside the `InputActionState` shown in the previous diagram (`m_State`). ```mermaid flowchart LR From 862570989fa2edad685bd9475f064f4cea5ce41b Mon Sep 17 00:00:00 2001 From: sue-arkin Date: Wed, 22 Jul 2026 11:53:55 +0100 Subject: [PATCH 3/7] Partial text update --- .../Documentation~/Architecture.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Packages/com.unity.inputsystem/Documentation~/Architecture.md b/Packages/com.unity.inputsystem/Documentation~/Architecture.md index cc6a7cc6b4..daf956a230 100644 --- a/Packages/com.unity.inputsystem/Documentation~/Architecture.md +++ b/Packages/com.unity.inputsystem/Documentation~/Architecture.md @@ -7,11 +7,11 @@ The Input System has a layered architecture that consists of a low-level layer a # 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 foundation of the Input System is the native backend code. This is platform-specific code that collects information about available devices and input data from devices. This code isn't part of the Input System package; it's 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](input-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 interfaces with the native backend using [events](input-events.md) that the native backend sends. These events notify the system of the creation and removal of [Input Devices](devices.md) and any updates to the Device states. For efficiency and to avoid creating 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](device-commands.md) 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. +The Input System can also send data back to the native backend in the form of [commands](device-commands.md) 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) @@ -90,11 +90,11 @@ flowchart TB class InputManager manager; ``` -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 low-level Input System code processes and interprets the memory from the event stream that the built-in back end 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](control-state.md) in memory, so that the state always contains an up-to-date representation of the Device and all its Controls. +When the Input System discovers a device in the event stream, it creates a device representation for it. The low-level code sees a device as a block of raw, unmanaged memory. When the low-level code receives a state event for a device, it writes the data from the state event into the device's [state representation](control-state.md) in memory. This means 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. +The low-level system code also contains structs that describe the data layout of commonly known devices. # Input System (high-level) From 09df47c4d3801e2f234781ae2c2e4c64208fa94b Mon Sep 17 00:00:00 2001 From: sue-arkin Date: Mon, 3 Aug 2026 09:38:45 +0100 Subject: [PATCH 4/7] Continuing to work on the text --- .../Documentation~/Architecture.md | 38 ++++++++++--------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/Packages/com.unity.inputsystem/Documentation~/Architecture.md b/Packages/com.unity.inputsystem/Documentation~/Architecture.md index daf956a230..5bca77b3bf 100644 --- a/Packages/com.unity.inputsystem/Documentation~/Architecture.md +++ b/Packages/com.unity.inputsystem/Documentation~/Architecture.md @@ -3,23 +3,24 @@ uid: input-system-architecture --- # Architecture -The Input System has a layered architecture that consists of a low-level layer and a high-level layer. +The Input System architecture has two layers: low-level high-level. It interacts with the built-in back end in the Unity Editor. -# Native backend +## The built-in back end -The foundation of the Input System is the native backend code. This is platform-specific code that collects information about available devices and input data from devices. This code isn't part of the Input System package; it's 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 foundation of the Input System is the built-in back end code. This is platform-specific code that collects information about available devices and input data from devices. This code isn't part of the Input System package; it's 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](input-events.md) that the native backend sends. These events notify the system of the creation and removal of [Input Devices](devices.md) and any updates to the Device states. For efficiency and to avoid creating garbage, the native backend reports these events as a simple buffer of raw, unmanaged memory containing a stream of events. +The Input System interfaces with the built-in back end in one of two ways: -The Input System can also send data back to the native backend in the form of [commands](device-commands.md) 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. +- With [events](input-events.md) that the built-in back end sends. These events notify the system of the creation and removal of [Input devices](devices.md) and any updates to the device states. For efficiency, the built-in back end reports these events as a simple buffer of raw, unmanaged memory containing a stream of events. +- Sending data back to the built-in back end in the form of [commands](device-commands.md) sent to devices, which are also buffers of memory that the built-in back end interprets. These commands can have different meanings for different device types and platforms. -# Input System (low-level) +## Low-level diagram The diagram of the low-level Input System reads top-to-bottom as a layered pipeline: -1. The native platform backends at the bottom feed the InputManager. +1. The built-in platform back ends feed the InputManager. 1. The InputManager uses layouts to build devices. -1. The device's state is stored in Input State Memory at the top. +1. The device's state is stored in Input State Memory. ```mermaid flowchart TB @@ -68,14 +69,14 @@ flowchart TB EQ["Event Queue"] BEQ["Background Event Queue (async; flushes into the foreground queue)"] - Backends["Platform Backends + back ends["Platform back ends Windows · macOS · Linux · UWP · iOS · Android · Switch · Xbox · PS4 · WebGL · XR"] - Backends --> DDQ & EQ & BEQ + back ends --> DDQ & EQ & BEQ DDQ -->|"Device Discovered"| InputManager EQ -->|"Update (flushes event buffers)"| InputManager InputManager -->|"Queue Event"| EQ - InputManager -->|"Device Command (IOCTL-style)"| Backends + InputManager -->|"Device Command (IOCTL-style)"| back ends %% ---------- Grouping by color ---------- classDef layout fill:#e6f0ff,stroke:#4a78c0,color:#000; @@ -85,7 +86,7 @@ flowchart TB classDef manager fill:#ffffff,stroke:#e0403f,stroke-width:2px,color:#000; class Mouse,Pen,Touchscreen,Pointer,DS_PS4,DS_HID,DualShock,Gamepad_L,Keyboard_L,Stick,Axis,Button,Dpad layout; class Gamepad_D,leftStick,x,y,up,down,left,right,Keyboard_D,a,b,c,d device; - class DDQ,EQ,BEQ,Backends runtime; + class DDQ,EQ,BEQ,back ends runtime; class StateMemory mem; class InputManager manager; ``` @@ -96,7 +97,7 @@ When the Input System discovers a device in the event stream, it creates a devic The low-level system code also contains structs that describe the data layout of commonly known devices. -# Input System (high-level) +## High-level diagram The high-level system is easiest to understand in two parts: @@ -124,7 +125,7 @@ flowchart LR %% ---------- Runtime ---------- StateEvent["StateEvent (KeyboardState) - NativeInputSystem.onUpdate"] -->|feeds| OnUpdate["InputManager.OnUpdate()"] + built-inInputSystem.onUpdate"] -->|feeds| OnUpdate["InputManager.OnUpdate()"] %% ---------- Action state ---------- AState(["InputActionState @@ -192,8 +193,11 @@ flowchart LR class trig,bind,ctrl,State astate; ``` -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-specification.md). +The high-level Input System code uses [layouts](layouts.md) to interpret the data in a device's state buffers. The layouts describe a device's data and its controls in memory. The Input System creates layouts from either the predefined structs of commonly known devices supplied by the low-level system, or dynamically at runtime, for example, for [generic HIDs](hid-specification.md). -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. +Based on the information in the layouts, the Input System creates representations for each of the device's [controls](controls.md). You can now read the state of each of the device's controls individually. -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](bindings.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](set-callbacks-on-actions.md). 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). +As part of the high-level system, you can also: + +- Build another abstraction layer to map controls to your application mechanics: Use [actions](actions.md) to [bind](bindings.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](set-callbacks-on-actions.md). +- 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. \ No newline at end of file From b1b13aa1154ff7208aae7780c5a11efa9cefe69d Mon Sep 17 00:00:00 2001 From: sue-arkin Date: Mon, 3 Aug 2026 10:16:59 +0100 Subject: [PATCH 5/7] Reorging diagrams --- .../Documentation~/Architecture.md | 182 ++++++++++++------ 1 file changed, 125 insertions(+), 57 deletions(-) diff --git a/Packages/com.unity.inputsystem/Documentation~/Architecture.md b/Packages/com.unity.inputsystem/Documentation~/Architecture.md index 5bca77b3bf..930ebd408c 100644 --- a/Packages/com.unity.inputsystem/Documentation~/Architecture.md +++ b/Packages/com.unity.inputsystem/Documentation~/Architecture.md @@ -16,79 +16,147 @@ The Input System interfaces with the built-in back end in one of two ways: ## Low-level diagram -The diagram of the low-level Input System reads top-to-bottom as a layered pipeline: +The low-level Input System reads top-to-bottom as a layered pipeline. It's shown here as three linked diagrams, one per stage: 1. The built-in platform back ends feed the InputManager. -1. The InputManager uses layouts to build devices. +1. The InputManager uses layouts to build devices. 1. The device's state is stored in Input State Memory. +Each diagram ends with a signpost (the flag-shaped node) that shows where it hands off to the next. + +### 1. Platform back ends feed the InputManager + +The built-in back ends push discovery and state events into queues that drive the InputManager. The InputManager, in turn, sends commands back to the back ends. + ```mermaid flowchart TB - %% ---------- Input State Memory (top) ---------- - StateMemory["Input State Memory - (unmanaged raw memory — each device and control - gets a chunk that stores its current state)"] - - %% ---------- Devices (built from layouts) ---------- - Gamepad_D["Gamepad (device)"] --> leftStick - leftStick --> x & y & up & down & left & right - Keyboard_D["Keyboard (device)"] --> a & b & c & d - leftStick -->|"state written to"| StateMemory - Keyboard_D -->|"state written to"| StateMemory - - %% ---------- Layouts (describe how to build controls and devices) ---------- - Mouse -->|derives| Pointer - Pen -->|derives| Pointer - Touchscreen -->|derives| Pointer - DS_PS4["DualShock (PS4)"] --> DualShock - DS_HID["DualShock (HID)"] --> DualShock - DualShock --> Gamepad_L["Gamepad (layout)"] - Keyboard_L["Keyboard (layout)"] - Stick(("Stick")) - Axis(("Axis")) - Button(("Button")) - Dpad(("Dpad")) - - %% Layout building blocks build the individual device controls - Gamepad_L -.->|builds| Gamepad_D - Stick -.->|builds| leftStick - Axis -.->|builds| x & y - Button -.->|builds| up & down & left & right - Keyboard_L -.->|builds| Keyboard_D - - %% ---------- InputManager (middle) ---------- - InputManager(["InputManager - Matches layouts to devices (InputDeviceMatcher), - builds devices (InputDeviceBuilder), creates & updates them"]) - Gamepad_L -->|"searched by"| InputManager - InputManager -->|"creates & updates"| Gamepad_D - InputManager -->|"creates & updates"| Keyboard_D - - %% ---------- Input Runtime (bottom) ---------- + %% Diagram 1 of 3: Platform back ends feed the InputManager + backends["Platform back ends + Windows · macOS · Linux · UWP · iOS · Android + · Switch · Xbox · PS4 · Web · XR"] DDQ["Device Discovery Queue"] EQ["Event Queue"] BEQ["Background Event Queue (async; flushes into the foreground queue)"] - back ends["Platform back ends - Windows · macOS · Linux · UWP · iOS · Android - · Switch · Xbox · PS4 · WebGL · XR"] - back ends --> DDQ & EQ & BEQ + InputManager(["InputManager + Matches layouts to devices (InputDeviceMatcher), + builds devices (InputDeviceBuilder), creates & updates them"]) + + backends --> DDQ & EQ & BEQ DDQ -->|"Device Discovered"| InputManager EQ -->|"Update (flushes event buffers)"| InputManager InputManager -->|"Queue Event"| EQ - InputManager -->|"Device Command (IOCTL-style)"| back ends + InputManager -->|"Device Command (IOCTL-style)"| backends + + InputManager -.-> out1>"→ Diagram 2: the InputManager builds devices from layouts"] + + classDef runtime fill:#fdf3d0,stroke:#b9962e,color:#000; + classDef manager fill:#ffffff,stroke:#e0403f,stroke-width:2px,color:#000; + classDef signpost fill:#f2f2f2,stroke:#999,color:#000; + class backends,DDQ,EQ,BEQ runtime; + class InputManager manager; + class out1 signpost; +``` + +### 2. The InputManager uses layouts to build devices + +Layouts derive from one another and, together with reusable control building blocks, describe how to build devices and their controls. The InputManager searches these layouts and creates the concrete devices. + +```mermaid +flowchart TB + %% Diagram 2 of 3: The InputManager uses layouts to build devices + %% Portrait layout: bands stack top-to-bottom; each band is compact left-to-right. + + in2>"→ from Diagram 1: the InputManager"] -.-> InputManager + InputManager(["InputManager + Matches layouts to devices, + then creates & updates them"]) + + %% ---- Band A: layouts derive from one another ---- + subgraph LAYOUTS["Layouts describe how to build devices"] + direction LR + Mouse -->|derives| Pointer + Pen -->|derives| Pointer + Touchscreen -->|derives| Pointer + DS_PS4["DualShock (PS4)"] --> DualShock + DS_HID["DualShock (HID)"] --> DualShock + DualShock --> Gamepad_L["Gamepad (layout)"] + Keyboard_L["Keyboard (layout)"] + end + + %% ---- Band B: reusable building blocks build the controls ---- + subgraph BLOCKS["Reusable building blocks build the controls"] + direction LR + Stick(("Stick")) -.-> leftStick["leftStick"] + Axis(("Axis")) -.-> axes["x · y"] + Button(("Button")) -.-> buttons["up · down + left · right"] + Dpad(("Dpad")) + end + + %% ---- Band C: the devices the InputManager creates ---- + subgraph DEVICES["Devices"] + direction LR + Gamepad_D["Gamepad (device)"] + Keyboard_D["Keyboard (device)"] + end + + %% ---- Cross-band flow (top-to-bottom) ---- + InputManager -->|"searches"| LAYOUTS + LAYOUTS -.->|"build"| DEVICES + BLOCKS -.->|"build the controls in"| DEVICES + InputManager -->|"creates & updates"| DEVICES + + DEVICES -.-> out2>"→ Diagram 3: device state is stored in memory"] - %% ---------- Grouping by color ---------- classDef layout fill:#e6f0ff,stroke:#4a78c0,color:#000; classDef device fill:#e8f7e8,stroke:#4aa04a,color:#000; - classDef runtime fill:#fdf3d0,stroke:#b9962e,color:#000; - classDef mem fill:#f0e6f6,stroke:#8a5ea0,color:#000; classDef manager fill:#ffffff,stroke:#e0403f,stroke-width:2px,color:#000; + classDef signpost fill:#f2f2f2,stroke:#999,color:#000; class Mouse,Pen,Touchscreen,Pointer,DS_PS4,DS_HID,DualShock,Gamepad_L,Keyboard_L,Stick,Axis,Button,Dpad layout; - class Gamepad_D,leftStick,x,y,up,down,left,right,Keyboard_D,a,b,c,d device; - class DDQ,EQ,BEQ,back ends runtime; - class StateMemory mem; + class Gamepad_D,Keyboard_D,leftStick,axes,buttons device; class InputManager manager; + class in2,out2 signpost; +``` + +### 3. The device's state is stored in Input State Memory + +Each built device exposes a tree of controls. When state events arrive, the device and control state is written into Input State Memory, where each device and control has its own chunk of unmanaged memory. + +```mermaid +flowchart LR + %% Diagram 3 of 3: The device's state is stored in Input State Memory + %% Left-to-right flow so each device's controls stack vertically at a readable size. + in3>"→ from Diagram 2: the built devices"] -.-> GP & KB + + subgraph GP["Gamepad (device)"] + direction LR + leftStick["leftStick"] --> x & y & up & down & left & right + end + + subgraph KB["Keyboard (device)"] + direction LR + a + b + c + d + end + + StateMemory["Input State Memory + (unmanaged raw memory — each device and + control gets a chunk that stores its current state)"] + + GP -->|"state written to"| StateMemory + KB -->|"state written to"| StateMemory + + classDef device fill:#e8f7e8,stroke:#4aa04a,color:#000; + classDef mem fill:#f0e6f6,stroke:#8a5ea0,color:#000; + classDef signpost fill:#f2f2f2,stroke:#999,color:#000; + class leftStick,x,y,up,down,left,right,a,b,c,d device; + class StateMemory mem; + class in3 signpost; + style GP fill:#f4faf4,stroke:#4aa04a,color:#000; + style KB fill:#f4faf4,stroke:#4aa04a,color:#000; ``` The low-level Input System code processes and interprets the memory from the event stream that the built-in back end provides, and dispatches individual events. @@ -114,7 +182,7 @@ The first diagram is for the runtime data flow: 1. The resulting action fires a callback on the `PlayerInput` component in the scene. ```mermaid -flowchart LR +flowchart TB %% ---------- Devices ---------- Keyboard["Keyboard"] --> space["space"] @@ -125,7 +193,7 @@ flowchart LR %% ---------- Runtime ---------- StateEvent["StateEvent (KeyboardState) - built-inInputSystem.onUpdate"] -->|feeds| OnUpdate["InputManager.OnUpdate()"] + built-in InputSystem.onUpdate"] -->|feeds| OnUpdate["InputManager.OnUpdate()"] %% ---------- Action state ---------- AState(["InputActionState @@ -161,7 +229,7 @@ The second diagram is for the asset structure: 1. At runtime these populate the arrays inside the `InputActionState` shown in the previous diagram (`m_State`). ```mermaid -flowchart LR +flowchart TB %% ---------- Asset hierarchy ---------- Asset["InputActionAsset: MyGame.inputactions devices = [ Keyboard ] From b73e80475f4210534ae6cc45e0749a88709877e0 Mon Sep 17 00:00:00 2001 From: sue-arkin Date: Mon, 3 Aug 2026 11:40:45 +0100 Subject: [PATCH 6/7] enduser-docs, but no human review yet --- .../Documentation~/Architecture.md | 180 +++++++++++------- 1 file changed, 107 insertions(+), 73 deletions(-) diff --git a/Packages/com.unity.inputsystem/Documentation~/Architecture.md b/Packages/com.unity.inputsystem/Documentation~/Architecture.md index 930ebd408c..13b8adff3c 100644 --- a/Packages/com.unity.inputsystem/Documentation~/Architecture.md +++ b/Packages/com.unity.inputsystem/Documentation~/Architecture.md @@ -1,54 +1,80 @@ --- uid: input-system-architecture +description: Understand how the Input System's low-level and high-level layers turn platform input into actions that your application responds to. --- -# Architecture +# Input System architecture -The Input System architecture has two layers: low-level high-level. It interacts with the built-in back end in the Unity Editor. +Understand how the Input System's low-level and high-level layers turn platform input into actions that your application responds to. + +The Input System has two layers. The low-level layer receives raw input from the platform-specific back end that ships with Unity, and stores that input as device state in unmanaged memory. The high-level layer interprets that state as controls, actions, and bindings that your application code responds to. + +This page describes the built-in back end that supplies the input, then the low-level system that stores it, then the high-level system that interprets it. ## The built-in back end -The foundation of the Input System is the built-in back end code. This is platform-specific code that collects information about available devices and input data from devices. This code isn't part of the Input System package; it's 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 foundation of the Input System is the built-in back-end code. This platform-specific code collects information about the available devices, and the input data from those devices. The code isn't part of the Input System package; it ships with Unity itself, and it has an implementation for each runtime platform that Unity supports. As a result, Unity must release an update to fix some platform-specific input issues. A new version of the Input System package can't fix them. + +The Input System interfaces with the built-in back end in two ways: + +- The built-in back end sends [events](input-events.md) to the Input System. These events tell the Input System when the platform adds or removes an [input device](devices.md), and when a device's state changes. For efficiency, the built-in back end reports these events as a simple buffer of raw, unmanaged memory that contains a stream of events. +- The Input System sends [commands](device-commands.md) to devices in the built-in back end. Commands are also buffers of memory that the built-in back end interprets. A command can have a different meaning for each device type and platform. + +## The low-level system -The Input System interfaces with the built-in back end in one of two ways: +The low-level Input System code processes and interprets the memory in the event stream that the built-in back end provides. It then dispatches individual events. -- With [events](input-events.md) that the built-in back end sends. These events notify the system of the creation and removal of [Input devices](devices.md) and any updates to the device states. For efficiency, the built-in back end reports these events as a simple buffer of raw, unmanaged memory containing a stream of events. -- Sending data back to the built-in back end in the form of [commands](device-commands.md) sent to devices, which are also buffers of memory that the built-in back end interprets. These commands can have different meanings for different device types and platforms. +When the Input System discovers a device in the event stream, it creates a device representation for that device. The low-level code sees a device as a block of raw, unmanaged memory. When the low-level code receives a state event for a device, it writes the data from that event into the device's [state representation](control-state.md) in memory. The state therefore always holds an up-to-date representation of the device and all its controls. -## Low-level diagram +The low-level system code also contains structs that describe the data layout of commonly known devices. + +The low-level system works as a layered pipeline. The following three diagrams each show one stage of that pipeline: + +1. The platform back ends queue events for the `InputManager` class. +2. The `InputManager` class uses layouts to build devices. +3. Each device writes its state into input state memory. -The low-level Input System reads top-to-bottom as a layered pipeline. It's shown here as three linked diagrams, one per stage: +Each diagram ends with a node that names the diagram it hands off to. -1. The built-in platform back ends feed the InputManager. -1. The InputManager uses layouts to build devices. -1. The device's state is stored in Input State Memory. +**Note**: `InputManager` is the Input System class that owns devices and drives updates. Don't confuse it with the **Input Manager** window, which configures Unity's legacy input settings. -Each diagram ends with a signpost (the flag-shaped node) that shows where it hands off to the next. +The following table describes the color coding that all the diagrams on this page use: -### 1. Platform back ends feed the InputManager +| **Color** | **Represents** | +| :--- | :--- | +| Yellow | Platform back ends, and the runtime plumbing that carries events between them and the Input System. | +| White with a red border | The `InputManager` class. | +| Blue | Layouts, and the reusable control building blocks that layouts are made from. | +| Green | Devices and their controls. | +| Purple | Input state memory. | +| Lavender | The `InputActionState` object and the arrays it holds. | +| Orange | Action assets, action maps, actions, and bindings. | +| Gray | Scene GameObjects, and the nodes that link one diagram to the next. | -The built-in back ends push discovery and state events into queues that drive the InputManager. The InputManager, in turn, sends commands back to the back ends. +### 1. Platform back ends queue events + +The built-in back ends push discovery and state events into three queues that drive the `InputManager` class. The `InputManager` class sends commands back to the back ends. ```mermaid flowchart TB - %% Diagram 1 of 3: Platform back ends feed the InputManager + %% Diagram 1 of 3: platform back ends queue events backends["Platform back ends Windows · macOS · Linux · UWP · iOS · Android · Switch · Xbox · PS4 · Web · XR"] - DDQ["Device Discovery Queue"] - EQ["Event Queue"] - BEQ["Background Event Queue + DDQ["Device discovery queue"] + EQ["Event queue"] + BEQ["Background event queue (async; flushes into the foreground queue)"] InputManager(["InputManager Matches layouts to devices (InputDeviceMatcher), - builds devices (InputDeviceBuilder), creates & updates them"]) + builds devices (InputDeviceBuilder), creates and updates them"]) backends --> DDQ & EQ & BEQ - DDQ -->|"Device Discovered"| InputManager + DDQ -->|"Device discovered"| InputManager EQ -->|"Update (flushes event buffers)"| InputManager - InputManager -->|"Queue Event"| EQ - InputManager -->|"Device Command (IOCTL-style)"| backends + InputManager -->|"Queue event"| EQ + InputManager -->|"Device command (IOCTL-style)"| backends - InputManager -.-> out1>"→ Diagram 2: the InputManager builds devices from layouts"] + InputManager -.-> out1>"→ Diagram 2: layouts build devices"] classDef runtime fill:#fdf3d0,stroke:#b9962e,color:#000; classDef manager fill:#ffffff,stroke:#e0403f,stroke-width:2px,color:#000; @@ -58,19 +84,21 @@ flowchart TB class out1 signpost; ``` -### 2. The InputManager uses layouts to build devices +### 2. Layouts build devices + +Layouts derive from one another. Together with reusable control building blocks, they describe how to build devices and their controls. The `InputManager` class searches these layouts and creates the concrete devices. -Layouts derive from one another and, together with reusable control building blocks, describe how to build devices and their controls. The InputManager searches these layouts and creates the concrete devices. +For example, the `Mouse`, `Pen`, and `Touchscreen` layouts all derive from the `Pointer` layout, and the PS4 and HID variants of `DualShock` both derive from a shared `DualShock` layout that in turn derives from `Gamepad`. Building blocks such as `Stick`, `Axis`, `Button`, and `Dpad` supply the individual controls that each device exposes. ```mermaid flowchart TB - %% Diagram 2 of 3: The InputManager uses layouts to build devices - %% Portrait layout: bands stack top-to-bottom; each band is compact left-to-right. + %% Diagram 2 of 3: layouts build devices + %% Bands stack top-to-bottom; each band is compact left-to-right. - in2>"→ from Diagram 1: the InputManager"] -.-> InputManager + in2>"→ from Diagram 1: the InputManager class"] -.-> InputManager InputManager(["InputManager Matches layouts to devices, - then creates & updates them"]) + then creates and updates them"]) %% ---- Band A: layouts derive from one another ---- subgraph LAYOUTS["Layouts describe how to build devices"] @@ -94,7 +122,7 @@ flowchart TB Dpad(("Dpad")) end - %% ---- Band C: the devices the InputManager creates ---- + %% ---- Band C: the devices the InputManager class creates ---- subgraph DEVICES["Devices"] direction LR Gamepad_D["Gamepad (device)"] @@ -105,9 +133,9 @@ flowchart TB InputManager -->|"searches"| LAYOUTS LAYOUTS -.->|"build"| DEVICES BLOCKS -.->|"build the controls in"| DEVICES - InputManager -->|"creates & updates"| DEVICES + InputManager -->|"creates and updates"| DEVICES - DEVICES -.-> out2>"→ Diagram 3: device state is stored in memory"] + DEVICES -.-> out2>"→ Diagram 3: devices store state in memory"] classDef layout fill:#e6f0ff,stroke:#4a78c0,color:#000; classDef device fill:#e8f7e8,stroke:#4aa04a,color:#000; @@ -119,14 +147,16 @@ flowchart TB class in2,out2 signpost; ``` -### 3. The device's state is stored in Input State Memory +### 3. Devices store their state in memory -Each built device exposes a tree of controls. When state events arrive, the device and control state is written into Input State Memory, where each device and control has its own chunk of unmanaged memory. +Each built device exposes a tree of controls. When state events arrive, the Input System writes the device and control state into input state memory, where each device and control has its own chunk of unmanaged memory. + +For example, a `Gamepad` device exposes a `leftStick` control that resolves to the `x`, `y`, `up`, `down`, `left`, and `right` controls, and a `Keyboard` device exposes one control per key. Both devices write into the same input state memory. ```mermaid -flowchart LR - %% Diagram 3 of 3: The device's state is stored in Input State Memory - %% Left-to-right flow so each device's controls stack vertically at a readable size. +flowchart TB + %% Diagram 3 of 3: devices store their state in memory + %% Outer flow is top-to-bottom; subgraphs run left-to-right so controls stay readable. in3>"→ from Diagram 2: the built devices"] -.-> GP & KB subgraph GP["Gamepad (device)"] @@ -142,12 +172,12 @@ flowchart LR d end - StateMemory["Input State Memory + StateMemory["Input state memory (unmanaged raw memory — each device and control gets a chunk that stores its current state)"] - GP -->|"state written to"| StateMemory - KB -->|"state written to"| StateMemory + GP -->|"writes state to"| StateMemory + KB -->|"writes state to"| StateMemory classDef device fill:#e8f7e8,stroke:#4aa04a,color:#000; classDef mem fill:#f0e6f6,stroke:#8a5ea0,color:#000; @@ -159,41 +189,43 @@ flowchart LR style KB fill:#f4faf4,stroke:#4aa04a,color:#000; ``` -The low-level Input System code processes and interprets the memory from the event stream that the built-in back end provides, and dispatches individual events. +## The high-level system -When the Input System discovers a device in the event stream, it creates a device representation for it. The low-level code sees a device as a block of raw, unmanaged memory. When the low-level code receives a state event for a device, it writes the data from the state event into the device's [state representation](control-state.md) in memory. This means that the state always contains an up-to-date representation of the device and all its controls. +The high-level Input System code uses [layouts](Layouts.md) to interpret the data in a device's state buffers. Layouts describe a device's data and its controls in memory. The Input System creates layouts from the predefined structs of commonly known devices that the low-level system supplies, or dynamically at runtime. For example, the Input System creates layouts at runtime for [generic HIDs](hid-specification.md). -The low-level system code also contains structs that describe the data layout of commonly known devices. +Based on the information in the layouts, the Input System creates a representation for each of the device's [controls](controls.md). You can then read the state of each control individually. -## High-level diagram +The high-level system also lets you do the following: -The high-level system is easiest to understand in two parts: +- Map controls to your application's mechanics. Use [actions](Actions.md) to [bind](bindings.md) one or more controls to an input in your application. The Input System monitors these controls for state changes, and notifies your application logic through [callbacks](set-callbacks-on-actions.md). +- Specify more complex behaviors for your actions. [Processors](Processors.md) transform the input data before the Input System sends it to you, and [interactions](Interactions.md) let you specify patterns of input on a control to listen for, such as multi-taps. -- How input flows through the system at runtime. -- How actions are authored as assets. +Two diagrams describe the high-level system: one for how input flows through the system at runtime, and one for how you author actions as assets. Both diagrams show a single player. Each additional player has its own `InputActionState` object. Each additional player also has a cloned `InputActionAsset` object with its own device list and binding mask. -The diagram shows both parts for a single player; each additional player gets its own `InputActionState` and a cloned `InputActionAsset` with its own device list and binding mask. +### Runtime input flow -The first diagram is for the runtime data flow: +At runtime, input reaches your scene through four steps: -1. A device's control state is written into Input State memory. -1. A State Change Monitor notices the change. -1. The `InputActionState` is updated. -1. The resulting action fires a callback on the `PlayerInput` component in the scene. +1. The Input System writes a device's control state into input state memory. +2. A state change monitor notices the change. +3. The Input System updates the `InputActionState` object. +4. The resulting action fires a callback on the `PlayerInput` component in the scene. + +The following diagram traces those steps for a single control, the space key on a keyboard. The keyboard's space control stores its value as one bit of `KeyboardState`. A `StateEvent` object carrying that state feeds `InputManager.OnUpdate()`, which calls `NotifyControlStateChanged()` on the `InputActionState` object. That object holds three arrays: `triggerStates[]`, `bindingStates[]`, and `controls[]`. State change monitors update the binding and control arrays, and the trigger array notifies `InputUser`, which calls `OnActionTriggered()` on the `PlayerInput` component. ```mermaid flowchart TB %% ---------- Devices ---------- Keyboard["Keyboard"] --> space["space"] - %% ---------- Input State (unmanaged raw memory) ---------- + %% ---------- Input state memory ---------- KBbit["KeyboardState - 1 Bit for Space Key"] + 1 bit for the space key"] space -->|"stored in"| KBbit %% ---------- Runtime ---------- StateEvent["StateEvent (KeyboardState) - built-in InputSystem.onUpdate"] -->|feeds| OnUpdate["InputManager.OnUpdate()"] + from the built-in back end"] -->|feeds| OnUpdate["InputManager.OnUpdate()"] %% ---------- Action state ---------- AState(["InputActionState @@ -203,30 +235,31 @@ flowchart TB ctrl["controls[]"] AState --> trig & bind & ctrl OnUpdate ==>|"NotifyControlStateChanged()"| AState - KBbit -->|"State Change Monitor"| bind - space -->|"State Change Monitor"| ctrl + KBbit -->|"state change monitor"| bind + space -->|"state change monitor"| ctrl %% ---------- Callback out to the scene ---------- trig -->|triggers| IU["InputUser"] IU -->|"OnActionTriggered()"| PI["PlayerInput - (Scene GameObject)"] + (scene GameObject)"] - classDef device fill:#e6f0ff,stroke:#4a78c0,color:#000; - classDef state fill:#cfcfcf,stroke:#555,color:#000; + classDef device fill:#e8f7e8,stroke:#4aa04a,color:#000; + classDef mem fill:#f0e6f6,stroke:#8a5ea0,color:#000; classDef astate fill:#efe9ff,stroke:#7a5ec0,color:#000; classDef runtime fill:#fdf3d0,stroke:#b9962e,color:#000; classDef go fill:#d9d9d9,stroke:#666,color:#000; class Keyboard,space device; - class KBbit state; + class KBbit mem; class AState,trig,bind,ctrl astate; class StateEvent,OnUpdate runtime; class IU,PI go; ``` -The second diagram is for the asset structure: +### Action asset structure + +An `InputActionAsset` object contains action maps, actions, and bindings. At runtime, these populate the arrays inside the `InputActionState` object that the previous diagram shows. -1. An `InputActionAsset` contains maps, actions, and bindings. -1. At runtime these populate the arrays inside the `InputActionState` shown in the previous diagram (`m_State`). +The following diagram shows an asset named `MyGame.inputactions` that lists `Keyboard` as its device and masks bindings to the `KeyboardMouse` group. The asset contains a `gameplay` action map, which contains a `jump` action and two bindings for that action: `/space` in the `KeyboardMouse` group, and `/buttonSouth` in the `Gamepad` group. The action populates `triggerStates[]`, the bindings populate `bindingStates[]`, and the binding states resolve to `controls[]`. ```mermaid flowchart TB @@ -255,17 +288,18 @@ flowchart TB State(["InputActionState (m_State)"]) --- trig & bind & ctrl - classDef asset fill:#e8f7e8,stroke:#4aa04a,color:#000; + classDef asset fill:#ffeede,stroke:#c07a3a,color:#000; classDef astate fill:#efe9ff,stroke:#7a5ec0,color:#000; class Asset,Map,Act,Bind_a,Bind_b asset; class trig,bind,ctrl,State astate; ``` -The high-level Input System code uses [layouts](layouts.md) to interpret the data in a device's state buffers. The layouts describe a device's data and its controls in memory. The Input System creates layouts from either the predefined structs of commonly known devices supplied by the low-level system, or dynamically at runtime, for example, for [generic HIDs](hid-specification.md). - -Based on the information in the layouts, the Input System creates representations for each of the device's [controls](controls.md). You can now read the state of each of the device's controls individually. - -As part of the high-level system, you can also: +## Additional resources -- Build another abstraction layer to map controls to your application mechanics: Use [actions](actions.md) to [bind](bindings.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](set-callbacks-on-actions.md). -- 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. \ No newline at end of file +- [Input events](input-events.md) +- [Device commands](device-commands.md) +- [Control state](control-state.md) +- [Layouts](Layouts.md) +- [Controls](controls.md) +- [Actions](Actions.md) +- [Bindings](bindings.md) From 057bc9a5e09ecb18641f187a360f094879643aa6 Mon Sep 17 00:00:00 2001 From: sue-arkin Date: Tue, 4 Aug 2026 10:19:52 +0100 Subject: [PATCH 7/7] Textual review --- .../Documentation~/Architecture.md | 60 ++++++++++++++----- 1 file changed, 44 insertions(+), 16 deletions(-) diff --git a/Packages/com.unity.inputsystem/Documentation~/Architecture.md b/Packages/com.unity.inputsystem/Documentation~/Architecture.md index 13b8adff3c..195b39a5f3 100644 --- a/Packages/com.unity.inputsystem/Documentation~/Architecture.md +++ b/Packages/com.unity.inputsystem/Documentation~/Architecture.md @@ -12,7 +12,7 @@ This page describes the built-in back end that supplies the input, then the low- ## The built-in back end -The foundation of the Input System is the built-in back-end code. This platform-specific code collects information about the available devices, and the input data from those devices. The code isn't part of the Input System package; it ships with Unity itself, and it has an implementation for each runtime platform that Unity supports. As a result, Unity must release an update to fix some platform-specific input issues. A new version of the Input System package can't fix them. +The foundation of the Input System is the built-in back-end code. This platform-specific code collects information about the available devices, and the input data from those devices. The code isn't part of the Input System package; it ships with Unity itself, and it has an implementation for each runtime platform that Unity supports. The Input System interfaces with the built-in back end in two ways: @@ -29,19 +29,17 @@ The low-level system code also contains structs that describe the data layout of The low-level system works as a layered pipeline. The following three diagrams each show one stage of that pipeline: -1. The platform back ends queue events for the `InputManager` class. +1. The platforms' back ends queue events for the `InputManager` class. 2. The `InputManager` class uses layouts to build devices. 3. Each device writes its state into input state memory. -Each diagram ends with a node that names the diagram it hands off to. - -**Note**: `InputManager` is the Input System class that owns devices and drives updates. Don't confuse it with the **Input Manager** window, which configures Unity's legacy input settings. +**Note**: `InputManager` is the Input System class that owns devices and drives updates. It's not the **Input Manager** window, which configures Unity's legacy input settings. The following table describes the color coding that all the diagrams on this page use: | **Color** | **Represents** | | :--- | :--- | -| Yellow | Platform back ends, and the runtime plumbing that carries events between them and the Input System. | +| Yellow | Platform back ends, and the runtime pipes that carry events between them and the Input System. | | White with a red border | The `InputManager` class. | | Blue | Layouts, and the reusable control building blocks that layouts are made from. | | Green | Devices and their controls. | @@ -50,7 +48,7 @@ The following table describes the color coding that all the diagrams on this pag | Orange | Action assets, action maps, actions, and bindings. | | Gray | Scene GameObjects, and the nodes that link one diagram to the next. | -### 1. Platform back ends queue events +### Diagram 1: Platform back ends queue events The built-in back ends push discovery and state events into three queues that drive the `InputManager` class. The `InputManager` class sends commands back to the back ends. @@ -84,11 +82,15 @@ flowchart TB class out1 signpost; ``` -### 2. Layouts build devices +### Diagram 2: Layouts build devices Layouts derive from one another. Together with reusable control building blocks, they describe how to build devices and their controls. The `InputManager` class searches these layouts and creates the concrete devices. -For example, the `Mouse`, `Pen`, and `Touchscreen` layouts all derive from the `Pointer` layout, and the PS4 and HID variants of `DualShock` both derive from a shared `DualShock` layout that in turn derives from `Gamepad`. Building blocks such as `Stick`, `Axis`, `Button`, and `Dpad` supply the individual controls that each device exposes. +For example: + +- The `Mouse`, `Pen`, and `Touchscreen` layouts all derive from the `Pointer` layout. +- The PS4 and HID variants of `DualShock` both derive from a shared `DualShock` layout, which itself derives from `Gamepad`. +- Building blocks such as `Stick`, `Axis`, `Button`, and `Dpad` supply the individual controls that each device exposes. ```mermaid flowchart TB @@ -147,11 +149,16 @@ flowchart TB class in2,out2 signpost; ``` -### 3. Devices store their state in memory +### Diagram 3: Devices store their state in memory Each built device exposes a tree of controls. When state events arrive, the Input System writes the device and control state into input state memory, where each device and control has its own chunk of unmanaged memory. -For example, a `Gamepad` device exposes a `leftStick` control that resolves to the `x`, `y`, `up`, `down`, `left`, and `right` controls, and a `Keyboard` device exposes one control per key. Both devices write into the same input state memory. +For example: + +- A `Gamepad` device exposes a `leftStick` control that resolves to the `x`, `y`, `up`, `down`, `left`, and `right` controls. +- A `Keyboard` device exposes one control for each key. + +Both devices write into the same input state memory. ```mermaid flowchart TB @@ -200,9 +207,17 @@ The high-level system also lets you do the following: - Map controls to your application's mechanics. Use [actions](Actions.md) to [bind](bindings.md) one or more controls to an input in your application. The Input System monitors these controls for state changes, and notifies your application logic through [callbacks](set-callbacks-on-actions.md). - Specify more complex behaviors for your actions. [Processors](Processors.md) transform the input data before the Input System sends it to you, and [interactions](Interactions.md) let you specify patterns of input on a control to listen for, such as multi-taps. -Two diagrams describe the high-level system: one for how input flows through the system at runtime, and one for how you author actions as assets. Both diagrams show a single player. Each additional player has its own `InputActionState` object. Each additional player also has a cloned `InputActionAsset` object with its own device list and binding mask. +Two diagrams describe the high-level system: + +1. How input flows through the system at runtime. +1. How you author actions as assets. -### Runtime input flow +Both diagrams show a single player. Each additional player has: + +- Its own `InputActionState` object. +- A cloned `InputActionAsset` object with its own device list and binding mask. + +### Diagram 4: Runtime input flow At runtime, input reaches your scene through four steps: @@ -211,7 +226,13 @@ At runtime, input reaches your scene through four steps: 3. The Input System updates the `InputActionState` object. 4. The resulting action fires a callback on the `PlayerInput` component in the scene. -The following diagram traces those steps for a single control, the space key on a keyboard. The keyboard's space control stores its value as one bit of `KeyboardState`. A `StateEvent` object carrying that state feeds `InputManager.OnUpdate()`, which calls `NotifyControlStateChanged()` on the `InputActionState` object. That object holds three arrays: `triggerStates[]`, `bindingStates[]`, and `controls[]`. State change monitors update the binding and control arrays, and the trigger array notifies `InputUser`, which calls `OnActionTriggered()` on the `PlayerInput` component. +The following diagram traces those steps for a single control, the space key on a keyboard: + +1. The keyboard's space control stores its value as one bit of `KeyboardState`. +1. A `StateEvent` object carrying that state feeds `InputManager.OnUpdate()`, which calls `NotifyControlStateChanged()` on the `InputActionState` object. + That object holds three arrays: `triggerStates[]`, `bindingStates[]`, and `controls[]`. +1. State change monitors update the binding and control arrays. +1. The trigger array notifies `InputUser`, which calls `OnActionTriggered()` on the `PlayerInput` component. ```mermaid flowchart TB @@ -255,11 +276,18 @@ flowchart TB class IU,PI go; ``` -### Action asset structure +### Diagram 5: Action asset structure An `InputActionAsset` object contains action maps, actions, and bindings. At runtime, these populate the arrays inside the `InputActionState` object that the previous diagram shows. -The following diagram shows an asset named `MyGame.inputactions` that lists `Keyboard` as its device and masks bindings to the `KeyboardMouse` group. The asset contains a `gameplay` action map, which contains a `jump` action and two bindings for that action: `/space` in the `KeyboardMouse` group, and `/buttonSouth` in the `Gamepad` group. The action populates `triggerStates[]`, the bindings populate `bindingStates[]`, and the binding states resolve to `controls[]`. +The following diagram shows an asset named `MyGame.inputactions` that lists `Keyboard` as its device and masks bindings to the `KeyboardMouse` group: + +1. The asset contains a `gameplay` action map, which contains a `jump` action and two bindings for that action: + - `/space` in the `KeyboardMouse` group. + - `/buttonSouth` in the `Gamepad` group. +1. The action populates `triggerStates[]`. +1. The bindings populate `bindingStates[]`. +1. The binding states resolve to `controls[]`. ```mermaid flowchart TB