--- title: Input Action System description: The cross-platform Input Action System lets you connect actions and arrange bindings across various hardware inputs at edit time. --- import DefaultBindings from '../includes/default-bindings.md' The cross-platform **Input Action System** lets you connect [actions](#input-actions) and arrange [bindings](#input-bindings) across various hardware inputs at edit time. Combined with [contexts](#input-contexts), you can easily configure and edit a modular input system that works on any device in any phase of play. Use cases include: - A first-person shooter system with actions dynamically swapping in and out depending on if the player is in battle mode or spectator mode. - A comprehensive driving system equipped with acceleration/deceleration, car boosters, and refuel stations. - Hotkeys for an abilities system in a fighting game to swap out moves seamlessly without players missing a punch. ## Input contexts An `Class.InputContext` is a collection of actions which holds related [input actions](#input-actions), for example `PlayContext` for in‑experience character controls and `NavContext` for controls to navigate around UI menus. You can enable or disable contexts (and their corresponding actions) through their `Class.InputContext.Enabled|Enabled` property, such as to enable the `NavContext` when an inventory menu is open and then change to the `PlayContext` when the player closes the menu and returns to primary gameplay. Even if an experience may not use multiple input contexts initially, best practice is to create a primary context at the top level of any input system, for example the `PlayContext` instance for input that occurs during gameplay. 1. Insert a new `Class.InputContext` into `Class.StarterGui`. 2. Rename it to `PlayContext`. New InputContext instance inside StarterGui, renamed to PlayContext ## Input actions An `Class.InputAction` defines a gameplay action mechanic such as "Jump," "Sprint," or "Shoot." These actions are then mapped to hardware inputs using [input bindings](#input-bindings). An `Class.InputAction` can be of several variations depending on its `Class.InputAction.Type|Type` property (`Enum.InputActionType`). The default is `Enum.InputActionType|Bool`, designed to receive `true`/`false` values from press/release of inputs such as `Enum.KeyCode.ButtonA|ButtonA`, `Enum.KeyCode.E|E`, or `Enum.KeyCode.MouseLeftButton|MouseLeftButton`. The `Enum.InputActionType|Bool` type also exposes the `Class.InputBinding.UIButton|UIButton` property on child bindings, allowing you to easily hook up press/release of a specific `Class.GuiButton` for the action.
Input Action Type Example Usage
`Enum.InputActionType|Bool` Triggered actions such as jump, shoot, sprint, etc. with support for pressed/released thresholds on analog inputs.
`Enum.InputActionType|Direction1D` Variable zero-to-full actions such as a car's accelerator pedal or a view scope's zoom level.
`Enum.InputActionType|Direction2D` 2D directional movement such as camera rotation, or the standard Roblox character movement.
`Enum.InputActionType|Direction3D` 3D directional movement like an airborne vehicle that can levitate up/down, accelerate/decelerate, and drift left/right.
`Enum.InputActionType|ViewportPosition` 2D viewport coordinates like mouse input, such as for custom cursors or raycasting to select world objects.
To test an `Class.InputAction` for simple character sprinting: 1. Create a new `Class.InputAction` inside the `PlayContext` context within `Class.StarterGui`. Rename it to `CharacterSprint` to indicate its dedicated action. New InputAction instance inside an InputContext, renamed to CharacterSprint 2. In the [Properties](../studio/properties.md) window, notice that the action's `Class.InputAction.Type|Type` is `Enum.InputActionType|Bool` (default). This is a logical type for simple character sprinting as a boolean `true`/`false` action (character is either sprinting or not sprinting). Type property of an InputAction set to Bool ## Input bindings An `Class.InputBinding` defines which hardware binding should trigger the parent `Class.InputAction`, for example a key press, gamepad button, or tap on a touch‑enabled device. For [cross‑platform](../projects/cross-platform.md) compatibility, each `Class.InputAction` should have an `Class.InputBinding` for **gamepad**, **keyboard/mouse**, and **touch** as illustrated here. The `Class.InputAction.Type|Type` assigned to the parent `Class.InputAction` directly affects which general input types (key/button/tap, analog trigger, thumbstick, etc.) are valid for child `Class.InputBinding` instances. In turn, values sent to the parent action's connected events depend on a binding's chosen input type. See [input events](#input-events) for details on the correlation between action types, bindings, and return values. To hook up bindings for simple character sprinting: 1. Insert a new `Class.InputBinding` into the `CharacterSprint` action and rename it to `KeyboardBinding`. Then set the binding's `Class.InputBinding.KeyCode|KeyCode` property to `Enum.KeyCode.LeftShift|LeftShift`. 2. To ensure mouse Shift-lock does not interfere with the key binding, select `Class.StarterPlayer` in the [Explorer](../studio/explorer.md) and disable its `Class.StarterPlayer.EnableMouseLockOption|EnableMouseLockOption` in the [Properties](../studio/properties.md) window. 3. Insert another `Class.InputBinding` into the `CharacterSprint` action and rename it to `GamepadBinding`. Then set the binding's `Class.InputBinding.KeyCode|KeyCode` property to `Enum.KeyCode.ButtonY|ButtonY`. 4. Inside a `Class.ScreenGui` container inside `Class.StarterGui`, create an [on-screen button](../ui/buttons.md), rename it to `SprintButton`, and [position/resize](../ui/position-and-size.md) it as desired. 5. Insert another `Class.InputBinding` into the `CharacterSprint` action and rename it to `TouchBinding`. Then, in the [Properties](../studio/properties.md) window, link the binding's `Class.InputBinding.UIButton|UIButton` property to the `SprintButton` button you created previously inside `Class.StarterGui`. ## Input events The `Class.InputAction` instance has three built-in **events** to handle player input coming from `Class.InputBinding|InputBindings`. - `Class.InputAction.Pressed|Pressed` — This event fires only when the input action's `Class.InputAction.Type|Type` is set to `Enum.InputActionType|Bool`, and only when the state transitions from `false` to `true`. - `Class.InputAction.Released|Released` — This event fires only when the input action's `Class.InputAction.Type|Type` is set to `Enum.InputActionType|Bool`, and only when the state transitions from `true` to `false`. - `Class.InputAction.StateChanged|StateChanged` — This event fires for all input action types whenever the state changes, except if the state attempts to transition to the same state. Depending on the input action's `Class.InputAction.Type|Type` (`Enum.InputActionType|Bool`, `Enum.InputActionType|Direction1D`, `Enum.InputActionType|Direction2D`, `Enum.InputActionType|Direction3D`, or `Enum.InputActionType|ViewportPosition`) and the general input type coming from a child `Class.InputBinding` (key/button/tap, analog trigger, thumbstick, etc.), different values are returned to the `Class.InputAction.Pressed|Pressed`, `Class.InputAction.Released|Released`, and `Class.InputAction.StateChanged|StateChanged` event handlers. Examine the following tables to better understand the correlation. The `Enum.InputActionType|Bool` type is best for triggered actions such as jump, shoot, sprint, etc. with support for pressed/released thresholds on analog inputs.
Valid Input Types on `Class.InputBinding|InputBindings` Returned to the `Class.InputAction` Event(s)
Boolean inputs from keyboard keys or basic mouse/gamepad buttons through the binding's `Class.InputBinding.KeyCode|KeyCode` property, or a `Class.GuiButton` press/release through the binding's `Class.InputBinding.UIButton|UIButton` property.
  • `Class.InputAction.Pressed|Pressed` event:
    • `true` when pressed
  • `Class.InputAction.Released|Released` event:
    • `true` when released
  • `Class.InputAction.StateChanged|StateChanged` event:
    • `true` (pressed) or `false` (released)
Variable input amounts from analog inputs like gamepad triggers (`Enum.KeyCode.ButtonL2|ButtonL2`/`Enum.KeyCode.ButtonR2|ButtonR2`) through the binding's `Class.InputBinding.KeyCode|KeyCode` property.
  • `Class.InputAction.Pressed|Pressed` event:
    • `true` when trigger press is `>=` `Class.InputBinding.PressedThreshold|PressedThreshold`
  • `Class.InputAction.Released|Released` event:
    • `true` when trigger press is `<=` `Class.InputBinding.ReleasedThreshold|ReleasedThreshold`
  • `Class.InputAction.StateChanged|StateChanged` event:
    • `true` when trigger press is `>=` `Class.InputBinding.PressedThreshold|PressedThreshold`
    • `false` when trigger press is `<=` `Class.InputBinding.ReleasedThreshold|ReleasedThreshold`
The `Enum.InputActionType|Direction1D` type is best for variable zero‑to‑full actions such as a car's accelerator pedal or a view scope's zoom level.
Valid Input Types on `Class.InputBinding|InputBindings` Returned to the `Class.InputAction` Event(s)
Variable input amounts from analog inputs like gamepad triggers (`Enum.KeyCode.ButtonL2|ButtonL2`/`Enum.KeyCode.ButtonR2|ButtonR2`) through the binding's `Class.InputBinding.KeyCode|KeyCode`, `Class.InputBinding.Up|Up`, and `Class.InputBinding.Down|Down` properties.
  • `Class.InputAction.StateChanged|StateChanged` event:
    • `0` to `1` (fully released to fully pressed) through the `Class.InputBinding.KeyCode|KeyCode` or `Class.InputBinding.Up|Up` properties
    • `0` to `-1` (fully released to fully pressed) through the `Class.InputBinding.Down|Down` property
Boolean inputs from keyboard keys or basic mouse/gamepad buttons through the binding's `Class.InputBinding.KeyCode|KeyCode`, `Class.InputBinding.Up|Up`, and `Class.InputBinding.Down|Down` properties.
  • `Class.InputAction.StateChanged|StateChanged` event:
    • `1` (pressed) or `0` (released) through the `Class.InputBinding.KeyCode|KeyCode` or `Class.InputBinding.Up|Up` properties
    • `-1` (pressed) or `0` (released) through the `Class.InputBinding.Down|Down` property
The `Enum.InputActionType|Direction2D` type is best for 2D directional movement such as camera rotation, or the standard Roblox character movement.
Valid Input Types on `Class.InputBinding|InputBindings` Returned to the `Class.InputAction` Event(s)
Variable input amounts from 2D analog inputs like gamepad thumbsticks (`Enum.KeyCode.Thumbstick1|Thumbstick1`/`Enum.KeyCode.Thumbstick2|Thumbstick2`) through the binding's `Class.InputBinding.KeyCode|KeyCode` property.
  • `Class.InputAction.StateChanged|StateChanged` event:
    • `Datatype.Vector2` between `(-1, -1)` and `(1, 1)`
Variable input amounts from analog inputs like gamepad triggers (`Enum.KeyCode.ButtonL2|ButtonL2`/`Enum.KeyCode.ButtonR2|ButtonR2`) through the binding's `Class.InputBinding.Up|Up`, `Class.InputBinding.Down|Down`, `Class.InputBinding.Left|Left`, and `Class.InputBinding.Right|Right` properties.
  • `Class.InputAction.StateChanged|StateChanged` event:
    • `Datatype.Vector2` with `Datatype.Vector2.Y|Y` component between `0` and `1` (fully released to fully pressed) through the `Class.InputBinding.Up|Up` property
    • `Datatype.Vector2` with `Datatype.Vector2.Y|Y` component between `0` and `-1` (fully released to fully pressed) through the `Class.InputBinding.Down|Down` property
    • `Datatype.Vector2` with `Datatype.Vector2.X|X` component between `0` and `-1` (fully released to fully pressed) through the `Class.InputBinding.Left|Left` property
    • `Datatype.Vector2` with `Datatype.Vector2.X|X` component between `0` and `1` (fully released to fully pressed) through the `Class.InputBinding.Right|Right` property
Boolean inputs from keyboard keys or basic mouse/gamepad buttons through the binding's `Class.InputBinding.Up|Up`, `Class.InputBinding.Down|Down`, `Class.InputBinding.Left|Left`, and `Class.InputBinding.Right|Right` properties.
  • `Class.InputAction.StateChanged|StateChanged` event:
    • `Datatype.Vector2` of `(0, 1)` (pressed) or `(0, 0)` (released) through the `Class.InputBinding.Up|Up` property
    • `Datatype.Vector2` of `(0, -1)` (pressed) or `(0, 0)` (released) through the `Class.InputBinding.Down|Down` property
    • `Datatype.Vector2` of `(-1, 0)` (pressed) or `(0, 0)` (released) through the `Class.InputBinding.Left|Left` property
    • `Datatype.Vector2` of `(1, 0)` (pressed) or `(0, 0)` (released) through the `Class.InputBinding.Right|Right` property
The `Enum.InputActionType|Direction3D` type is best for 3D directional movement like an airborne vehicle that can levitate up/down, accelerate/decelerate, and drift left/right.
Valid Input Types on `Class.InputBinding|InputBindings` Returned to the `Class.InputAction` Event(s)
Variable input amounts from analog inputs like gamepad triggers (`Enum.KeyCode.ButtonL2|ButtonL2`/`Enum.KeyCode.ButtonR2|ButtonR2`) through the binding's `Class.InputBinding.Up|Up`, `Class.InputBinding.Down|Down`, `Class.InputBinding.Left|Left`, `Class.InputBinding.Right|Right`, `Class.InputBinding.Forward|Forward`, and `Class.InputBinding.Backward|Backward` properties.
  • `Class.InputAction.StateChanged|StateChanged` event:
    • `Datatype.Vector3` with `Datatype.Vector3.Y|Y` component between `0` and `1` (fully released to fully pressed) through the `Class.InputBinding.Up|Up` property
    • `Datatype.Vector3` with `Datatype.Vector3.Y|Y` component between `0` and `-1` (fully released to fully pressed) through the `Class.InputBinding.Down|Down` property
    • `Datatype.Vector3` with `Datatype.Vector3.X|X` component between `0` and `-1` (fully released to fully pressed) through the `Class.InputBinding.Left|Left` property
    • `Datatype.Vector3` with `Datatype.Vector3.X|X` component between `0` and `1` (fully released to fully pressed) through the `Class.InputBinding.Right|Right` property
    • `Datatype.Vector3` with `Datatype.Vector3.Z|Z` component between `0` and `-1` (fully released to fully pressed) through the `Class.InputBinding.Forward|Forward` property
    • `Datatype.Vector3` with `Datatype.Vector3.Z|Z` component between `0` and `1` (fully released to fully pressed) through the `Class.InputBinding.Backward|Backward` property
Boolean inputs from keyboard keys or basic mouse/gamepad buttons through the binding's `Class.InputBinding.Up|Up`, `Class.InputBinding.Down|Down`, `Class.InputBinding.Left|Left`, `Class.InputBinding.Right|Right`, `Class.InputBinding.Forward|Forward`, and `Class.InputBinding.Backward|Backward` properties.
  • `Class.InputAction.StateChanged|StateChanged` event:
    • `Datatype.Vector3` of `(0, 1, 0)` (pressed) or `(0, 0, 0)` (released) through the `Class.InputBinding.Up|Up` property
    • `Datatype.Vector3` of `(0, -1, 0)` (pressed) or `(0, 0, 0)` (released) through the `Class.InputBinding.Down|Down` property
    • `Datatype.Vector3` of `(-1, 0, 0)` (pressed) or `(0, 0, 0)` (released) through the `Class.InputBinding.Left|Left` property
    • `Datatype.Vector3` of `(1, 0, 0)` (pressed) or `(0, 0, 0)` (released) through the `Class.InputBinding.Right|Right` property
    • `Datatype.Vector3` of `(0, 0, -1)` (pressed) or `(0, 0, 0)` (released) through the `Class.InputBinding.Forward|Forward` property
    • `Datatype.Vector3` of `(0, 0, 1)` (pressed) or `(0, 0, 0)` (released) through the `Class.InputBinding.Backward|Backward` property
The `Enum.InputActionType|ViewportPosition` type is best for absolute 2D viewport coordinates of an input such as a mouse pointer or touch, which can be used for features like custom cursors or selecting objects.
Valid Input Types on `Class.InputBinding|InputBindings` Returned to the `Class.InputAction` Event(s)
Variable input amounts from positional inputs such as a mouse pointer (`Enum.KeyCode.MousePosition|MousePosition`) or touch (`Enum.KeyCode.Touch|Touch`).
  • `Class.InputAction.StateChanged|StateChanged` event:
    • `Datatype.Vector2` between `(0, 0)` and the maximum absolute `(X, Y)` pixel size in the viewport.
Note that returned `Datatype.Vector2`/`Datatype.Vector3` values for 2D/3D inputs will be normalized such that the magnitude is never greater than `1` (unless scaling is applied). For example, a 45° up+right press on a gamepad thumbstick will return a normalized `Datatype.Vector2` of `(0.7071, 0.7071)` instead of `(1, 1)`. In practical terms of character movement, this ensures that diagonal presses do not allow players to move faster diagonally than they would in a cardinal direction.
To connect events for simple character sprinting: 1. Insert a new `Class.LocalScript` into the `CharacterSprint` tree, alongside the various input bindings. 2. Paste the following code into the script. Note the `Class.InputAction.Pressed|Pressed` event connection on lines `13`‑`15` which doubles the character's walk speed when a sprint input binding is pressed, and the corresponding `Class.InputAction.Released|Released` event connection on lines `16`‑`18` which resets the walk speed to default when a sprint input binding is released. ```lua local Players = game:GetService("Players") local player = Players.LocalPlayer local character = player.Character if not character or character.Parent == nil then character = player.CharacterAdded:Wait() end local humanoid = character:WaitForChild("Humanoid") local defaultWalkSpeed = humanoid.WalkSpeed local inputAction = script.Parent inputAction.Pressed:Connect(function() humanoid.WalkSpeed = defaultWalkSpeed * 2 end) inputAction.Released:Connect(function() humanoid.WalkSpeed = defaultWalkSpeed end) ``` 3. Playtest your experience and test the character sprint action with the [bindings](#input-bindings) you chose previously: `Enum.KeyCode.LeftShift|LeftShift` for keyboard, `Enum.KeyCode.ButtonY|ButtonY` for gamepad, and the on‑screen `SprintButton` for touch‑enabled devices. Remember that you can use the [Controller Emulator](../studio/testing-modes.md#controller-emulation) to test gamepad inputs directly in Roblox Studio. ## Context changes Once you have an [input context](#input-contexts) such as `PlayContext`, you can enable/disable it during gameplay through scripting, change its `Class.InputContext.Priority|Priority` to determine which actions take precedence over others, and `Class.InputContext.Sink|Sink` inputs from being processed within contexts of lower priority. 1. To make it easier to switch contexts from other scripts, insert a new `Class.BindableEvent` into `Class.StarterGui` and rename it to `ContextEvent`. 2. Create a new `Class.LocalScript` inside `Class.StarterGui` and rename it to `UpdateContext`. 3. Inside the `UpdateContext` script, paste the following code: ```lua local Players = game:GetService("Players") local player = Players.LocalPlayer local playerGui = player.PlayerGui local contextEvent = playerGui:FindFirstChild("ContextEvent") -- Connect bindable event contextEvent.Event:Connect(function(targetContext, enabled) local context = playerGui:FindFirstChild(targetContext) if context then context.Enabled = enabled print(context.Name .. ": " .. tostring(context.Enabled)) else warn("InputContext not found!") end end) ``` 4. With the `UpdateContext` script in place, you can now update a named `Class.InputContext` by firing the bindable event, for example from another `Class.LocalScript` that powers a `Class.GuiButton` inside the `Class.ScreenGui` container. ```lua local Players = game:GetService("Players") local player = Players.LocalPlayer local playerGui = player.PlayerGui local contextEvent = playerGui:FindFirstChild("ContextEvent") local button = script.Parent button.Activated:Connect(function() -- Fire bindable event with target input context and enabled state contextEvent:Fire("PlayContext", true) end) ``` ## Default bindings