---
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`.
## 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. |
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).
## 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`.
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`.
| 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. |
|
| 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. |
|
| 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. |
|
| 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. |
|
| 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. |
|
| 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. |
|
| 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. |
|
| 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. |
|
| 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. |
|
| 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`). |
|
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