| title | description |
|---|---|
Input Action System |
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 and arrange bindings across various hardware inputs at edit time. Combined with 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.
An Class.InputContext is a collection of actions which holds related 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.
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.
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, Enum.KeyCode|E, or Enum.KeyCode|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. |
To test an Class.InputAction for simple character sprinting:
-
Create a new
Class.InputActioninside thePlayContextcontext withinClass.StarterGui. Rename it toCharacterSprintto indicate its dedicated action.
-
In the Properties window, notice that the action's
Class.InputAction.Type|TypeisEnum.InputActionType|Bool(default). This is a logical type for simple character sprinting as a booleantrue/falseaction (character is either sprinting or not sprinting).
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 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 for details on the correlation between action types, bindings, and return values.
To hook up bindings for simple character sprinting:
-
Insert a new
Class.InputBindinginto theCharacterSprintaction and rename it toKeyboardBinding. Then set the binding'sClass.InputBinding.KeyCode|KeyCodeproperty toEnum.KeyCode|LeftShift.
-
To ensure mouse Shift-lock does not interfere with the key binding, select
Class.StarterPlayerin the Explorer and disable itsClass.StarterPlayer.EnableMouseLockOption|EnableMouseLockOptionin the Properties window.
-
Insert another
Class.InputBindinginto theCharacterSprintaction and rename it toGamepadBinding. Then set the binding'sClass.InputBinding.KeyCode|KeyCodeproperty toEnum.KeyCode|ButtonY.
-
Inside a
Class.ScreenGuicontainer insideClass.StarterGui, create an on-screen button, rename it toSprintButton, and position/resize it as desired.
-
Insert another
Class.InputBindinginto theCharacterSprintaction and rename it toTouchBinding. Then, in the Properties window, link the binding'sClass.InputBinding.UIButton|UIButtonproperty to theSprintButtonbutton you created previously insideClass.StarterGui.
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'sClass.InputAction.Type|Typeis set toEnum.InputActionType|Bool, and only when the state transitions fromfalsetotrue.Class.InputAction.Released|Released— This event fires only when the input action'sClass.InputAction.Type|Typeis set toEnum.InputActionType|Bool, and only when the state transitions fromtruetofalse.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, or Enum.InputActionType|Direction3D) 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.
| 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`/`Enum.KeyCode|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`/`Enum.KeyCode|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`/`Enum.KeyCode|Thumbstick2`) through the binding's `Class.InputBinding.KeyCode|KeyCode` property. |
|
| Variable input amounts from analog inputs like gamepad triggers (`Enum.KeyCode|ButtonL2`/`Enum.KeyCode|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`/`Enum.KeyCode|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. |
|
To connect events for simple character sprinting:
-
Insert a new
Class.LocalScriptinto theCharacterSprinttree, alongside the various input bindings.
-
Paste the following code into the script. Note the
Class.InputAction.Pressed|Pressedevent connection on lines13‑15which doubles the character's walk speed when a sprint input binding is pressed, and the correspondingClass.InputAction.Released|Releasedevent connection on lines16‑18which 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) ``` -
Playtest your experience and test the character sprint action with the bindings you chose previously:
Enum.KeyCode|LeftShiftfor keyboard,Enum.KeyCode|ButtonYfor gamepad, and the on‑screenSprintButtonfor touch‑enabled devices. Remember that you can use the Controller Emulator to test gamepad inputs directly in Roblox Studio.
Once you have an input context 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.
-
To make it easier to switch contexts from other scripts, insert a new
Class.BindableEventintoClass.StarterGuiand rename it toContextEvent.
-
Create a new
Class.LocalScriptinsideClass.StarterGuiand rename it toUpdateContext.
-
Inside the
UpdateContextscript, 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) ``` -
With the
UpdateContextscript in place, you can now update a namedClass.InputContextby firing the bindable event, for example from anotherClass.LocalScriptthat powers aClass.GuiButtoninside theClass.ScreenGuicontainer.<img src="../assets/studio/explorer/StarterGui-ScreenGui-TextButton.png" width="320" style={{marginBottom: 0}} />
```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) ```

