Input Action System

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.

Input contexts

An InputContext is a collection of actions which holds related input actions, for example PlayContext for in-game character controls and NavContext for controls to navigate around UI menus. You can enable/disable contexts (and their corresponding actions) through their 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 a game may not use multiple input contexts initially, it's recommended 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. RECOMMENDED
    Create a Folder named Inputs inside ReplicatedStorage to hold various input contexts.

    New Folder inside ReplicatedStorage, renamed to Inputs
  2. Insert a new InputContext into the folder and rename it to PlayContext.

    New InputContext instance inside ReplicatedStorage, renamed to PlayContext
  3. In the Properties window, set Priority to 2000 and enable Sink. A context with Sink enabled consumes input events for its bound KeyCodes at its priority level, blocking those inputs from reaching lower-priority contexts. This is practical for use cases like an inventory screen that should suppress specific gameplay inputs while open. In this example, PlayContext is given a high enough Priority to sink its bound inputs before the default PlayerScripts contexts process them.

Input actions

An InputAction defines a gameplay action mechanic such as "Jump," "Sprint," or "Shoot." These actions are then mapped to hardware inputs using input bindings.

An InputAction can be of several variations depending on its Type property (Enum.InputActionType). The default is Bool, designed to receive true/false values from press/release of inputs such as ButtonA, E, or MouseLeftButton.

Input Action TypeExample Usage
BoolTriggered actions such as jump, shoot, sprint, etc. with support for pressed/released thresholds on analog inputs.
Direction1DVariable zero-to-full actions such as a car's accelerator pedal or a view scope's zoom level.
Direction2D2D directional movement such as camera rotation, or the standard Roblox character movement.
Direction3D3D directional movement like an airborne vehicle that can levitate up/down, accelerate/decelerate, and drift left/right.
ViewportPosition2D viewport coordinates like mouse input, such as for custom cursors or raycasting to select world objects.

To test an InputAction for simple character sprinting:

  1. Create a new InputAction inside the PlayContext context within ReplicatedStorage. Rename it to CharacterSprint to indicate its dedicated action.

    New InputAction instance inside an InputContext, renamed to CharacterSprint
  2. In the Properties window, notice that the action's Type is 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 InputBinding defines which hardware binding should trigger the parent InputAction, for example a key press, gamepad button, or tap on a touch‑enabled device. For cross‑platform compatibility, each InputAction should have an InputBinding for gamepad, keyboard/mouse, and touch as illustrated here.

The Type assigned to the parent InputAction directly affects which general input types (key/button/tap, analog trigger, thumbstick, etc.) are valid for child 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:

  1. Insert a new InputBinding into the CharacterSprint action and rename it to KeyboardBinding. Then set the binding's KeyCode property to LeftShift.

  2. To ensure mouse Shift-lock does not interfere with the key binding, select StarterPlayer in the Explorer and disable its EnableMouseLockOption in the Properties window.

  3. Insert a second InputBinding into the CharacterSprint action and rename it to GamepadBinding. Then set the binding's KeyCode property to ButtonY.

  4. Inside a ScreenGui container inside StarterGui, create an on-screen button, rename it to SprintButton, and position/resize it as desired.

  5. Insert a third InputBinding into the CharacterSprint action and rename it to TouchBinding. Then, in the Properties window, link the binding's UIButton property to the SprintButton button you created previously inside StarterGui.

Input events

The InputAction instance has three built-in events to handle player input coming from InputBindings.

  • Pressed — This event fires only when the input action's Type is set to Bool, and only when the state transitions from false to true.
  • Released — This event fires only when the input action's Type is set to Bool, and only when the state transitions from true to false.
  • 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 Type (Bool, Direction1D, Direction2D, Direction3D, or ViewportPosition) and the general input type coming from a child InputBinding (key/button/tap, analog trigger, thumbstick, etc.), different values are returned to the Pressed, Released, and StateChanged event handlers. Examine the following tables to better understand the correlation.

The 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 InputBindingsReturned to the InputAction Event(s)
Boolean inputs from keyboard keys or basic mouse/gamepad buttons through the binding's KeyCode property, or a GuiButton press/release through the binding's UIButton property.
Variable input amounts from analog inputs like gamepad triggers (ButtonL2/ButtonR2) through the binding's KeyCode property.

To connect events for simple character sprinting:

  1. Insert a new Script into the CharacterSprint tree, alongside the various input bindings. Then set its RunContext to Client and rename it to OnActivate.

  2. Paste the following code into the OnActivate script. Note the Pressed event connection on lines 1315 which doubles the character's walk speed when a sprint input binding is pressed, and the corresponding Released event connection on lines 1618 which resets the walk speed to default when a sprint input binding is released.

    OnActivate (Client Script)

    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 game and test the character sprint action with the bindings you chose previously: LeftShift for keyboard, ButtonY for gamepad, and the on‑screen SprintButton for touch‑enabled devices. Remember that you can use the Controller Emulator to test gamepad inputs directly in Roblox Studio.

Context changes

Once you have an input context such as PlayContext, you can enable/disable it during gameplay through scripting, change its Priority to determine which actions take precedence over others, and Sink inputs from being processed within contexts of lower priority.

  1. To make it easier to switch contexts from other scripts, insert a new BindableEvent into your inputs folder within ReplicatedStorage and rename it to ContextEvent.

  2. Create a new Script at the same level, set its RunContext to Client, and rename it to UpdateContext.

  3. Inside the UpdateContext script, paste the following code:

    UpdateContext (Client Script)

    local ReplicatedStorage = game:GetService("ReplicatedStorage")
    local inputsFolder = ReplicatedStorage:WaitForChild("Inputs")
    local contextEvent = inputsFolder:WaitForChild("ContextEvent")
    -- Connect bindable event
    contextEvent.Event:Connect(function(targetContext, enabled)
    local context = inputsFolder: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 InputContext by firing the bindable event, for example from a LocalScript that powers a GuiButton inside a ScreenGui container.

    Button Script

    local ReplicatedStorage = game:GetService("ReplicatedStorage")
    local inputsFolder = ReplicatedStorage:WaitForChild("Inputs")
    local contextEvent = inputsFolder:WaitForChild("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

Roblox provides default input bindings for movement, camera control, and basic environment interaction — Roblox players are familiar with these controls, so you should only override them in specific cases. Also note that the reserved inputs cannot be overridden and will always operate with their intended purpose.

ActionMouse/KeyboardGamepadTouch
Open Roblox menuEscStart button (ButtonStart)N/A
Developer ConsoleF9N/AN/A
Fullscreen mode (Windows)
Show desktop (Mac)
F11N/AN/A
Record video (Windows)F12N/AN/A
Take screenshotPrintScreenN/AN/A
©2026 Roblox Corporation. Roblox, the Roblox logo and Powering Imagination are among our registered and unregistered trademarks in the U.S. and other countries.