Roblox accepts input from USB gamepads such as Xbox and PlayStation controllers. Since gamepads come in different varieties, you need to follow additional setup to verify that a player's gamepad inputs are usable in your experience.
To set up gamepad inputs, you can use ContextActionService or UserInputService to detect connected gamepads for a player's device, verify supported inputs that are compatible with Roblox, receive input, and more.
When binding gamepad inputs, see common control schemas to create a consistent gamepad experience for players. After inputs are set, you can enhance the player's experience by including haptic feedback on supported controllers.
Detecting Gamepads
You can detect whether a player's device currently has a gamepad active using the UserInputService.GamepadEnabled property.
Detecting Gamepad
local UserInputService = game:GetService("UserInputService")if UserInputService.GamepadEnabled thenprint("Player has gamepad enabled...")end
You can check for connected gamepads via UserInputService.GamepadConnected and UserInputService.GamepadDisconnected events. These events fire when a device is connected or disconnected respectively, and both events pass a Enum.UserInputType to the connected function indicating which gamepad caused the event. In most cases, the connected gamepad is Gamepad1.
Checking Connection and Disconnection
local UserInputService = game:GetService("UserInputService")
UserInputService.GamepadConnected:Connect(function(gamepad)
print("User has connected controller: " .. tostring(gamepad))
end)
UserInputService.GamepadDisconnected:Connect(function(gamepad)
print("User has disconnected controller: " .. tostring(gamepad))
end)
You can also query whether a particular controller is connected using the UserInputService:GetGamepadConnected() method. This takes a Enum.UserInputType as an argument and only accepts values of Gamepad1 through Gamepad8.
Query Specific Gamepad Connection
local UserInputService = game:GetService("UserInputService")if UserInputService:GetGamepadConnected(Enum.UserInputType.Gamepad1) thenprint("Gamepad1 is connected")elseif UserInputService:GetGamepadConnected(Enum.UserInputType.Gamepad2) thenprint("Gamepad2 is connected")end
Verifying Supported Inputs
Since gamepads can have different sets of inputs, you should check which inputs are supported with UserInputService:GetSupportedGamepadKeyCodes(). This method takes a Enum.UserInputType as an argument and returns a table with a list of all available inputs for the specified controller.
Verifying Supported Inputs
local UserInputService = game:GetService("UserInputService")local availableInputs = UserInputService:GetSupportedGamepadKeyCodes(Enum.UserInputType.Gamepad2)print("This controller supports the following controls:")for _, control in availableInputs doprint(control)end
Receiving Input
ContextActionService is useful for binding controls to both gamepads and other input sources such as mouse and keyboard inputs or mobile touchscreen buttons, or for binding multiple functions to a single button input on any device. For example, the following code sample binds an OpenSpellBook action to the gamepad's ButtonR2 button and the keyboard's B key.
ContextActionService Bind Action
local ContextActionService = game:GetService("ContextActionService")
local function openSpellBook(actionName, inputState, inputObject)
if inputState == Enum.UserInputState.Begin then
-- Open spell book
end
end
ContextActionService:BindAction("OpenSpellBook", openSpellBook, false, Enum.KeyCode.ButtonR2, Enum.KeyCode.B)
Alternatively, you can use UserInputService to bind controls directly from a gamepad. When detecting gamepad events through this service, use the InputBegan event to detect when the button was initially pressed and InputEnded to detect when the button is released. In the handling function, the InputObject.UserInputType property indicates which gamepad fired the event and InputObject.KeyCode indicates the specific button or stick that fired it.
UserInputService Button Press Detection
local UserInputService = game:GetService("UserInputService")
UserInputService.InputBegan:Connect(function(input)
if input.UserInputType == Enum.UserInputType.Gamepad1 then
if input.KeyCode == Enum.KeyCode.ButtonA then
print("Button A pressed on Gamepad1")
end
end
end)
Gamepad State
You can detect the current state of all buttons and sticks on a gamepad with the UserInputService:GetGamepadState() method. This is useful if you need to check the current gamepad inputs when a distinct event occurs in your experience, such as checking if specific buttons are being pressed when a character touches an object.
Checking State of Gamepad Inputs
local Players = game:GetService("Players")
local UserInputService = game:GetService("UserInputService")
local player = Players.LocalPlayer
local character = player.Character or player.CharacterAdded:Wait()
local leftFoot = character:WaitForChild("LeftFoot")
-- When left foot comes into contact with something, check the gamepad input state
leftFoot.Touched:Connect(function(hit)
local state = UserInputService:GetGamepadState(Enum.UserInputType.Gamepad1)
for _, input in state do
-- If the ButtonR2 is currently held, print out a message
if input.KeyCode == Enum.KeyCode.ButtonR2 and input.UserInputState == Enum.UserInputState.Begin then
print("Character's left foot touched something while holding right trigger")
end
end
end)
Trigger Pressure
You can detect how much pressure is being placed on gamepad triggers by checking the Position.Z value of the input trigger.
Testing Trigger Pressure
local UserInputService = game:GetService("UserInputService")
UserInputService.InputChanged:Connect(function(input)
if input.UserInputType == Enum.UserInputType.Gamepad1 then
if input.KeyCode == Enum.KeyCode.ButtonL1 then
print("Pressure on left trigger has changed:", input.Position.Z)
elseif input.KeyCode == Enum.KeyCode.ButtonR1 then
print("Pressure on right trigger has changed:", input.Position.Z)
end
end
end)
Common Control Schemas
Gamepads come in a variety of shapes and sizes. As with any method of player input, it's best to create some consistency across different games and experiences.
The following are common input binds that will help players immediately feel familiar and comfortable with the gamepad controls:
Input | Common Use Cases |
---|---|
ButtonA | Accepts player prompts or GUI selections. Alternatively used for primary actions such as jumping. |
ButtonB | Cancels player prompts or GUI selections. Alternatively used for secondary actions such as a dodge, roll, or sprint. |
Thumbstick1 | Generally associated with character movement. |
Thumbstick2 | Generally associated with camera movement. |
ButtonL2, ButtonR2 | Generally used for primary actions, such as shooting. |
ButtonL1, ButtonR1, ButtonX, ButtonY | Secondary actions such as reloading, targeting, or accessing an inventory or minimap. |
Haptic Feedback
Many gamepad controllers have motors built in to provide haptic feedback. Adding rumbles and vibrations can greatly enhance a player's experience and provide subtle feedback beyond visuals or audio. You can use the HapticService to verify vibration support before turning on the motors.
Vibration Support
Not all controllers have motors so it is important to check for support before attempting to use the haptic motors. To query if a given controller has vibration support, call HapticService:IsVibrationSupported().
Check Vibration Support
local HapticService = game:GetService("HapticService")local gamepad = Enum.UserInputType.Gamepad1local isVibrationSupported = HapticService:IsVibrationSupported(gamepad)
Some controllers have multiple motors for various scales of vibration. Once you've checked if a gamepad supports vibration, you should also check if it supports the motors you intend to use through HapticService:IsMotorSupported().
Check Motors Supported
local HapticService = game:GetService("HapticService")local gamepad = Enum.UserInputType.Gamepad1local isVibrationSupported = HapticService:IsVibrationSupported(gamepad)if isVibrationSupported thenlocal largeMotor = HapticService:IsMotorSupported(gamepad, Enum.VibrationMotor.Large)local smallMotor = HapticService:IsMotorSupported(gamepad, Enum.VibrationMotor.Small)local leftTriggerMotor = HapticService:IsMotorSupported(gamepad, Enum.VibrationMotor.LeftTrigger)local rightTriggerMotor = HapticService:IsMotorSupported(gamepad, Enum.VibrationMotor.RightTrigger)local leftHandMotor = HapticService:IsMotorSupported(gamepad, Enum.VibrationMotor.LeftHand)local rightHandMotor = HapticService:IsMotorSupported(gamepad, Enum.VibrationMotor.RightHand)end
Size or Location | Description |
---|---|
Large | Larger motor, useful for generic rumble. |
Small | Smaller motor, useful for more subtle rumbles like tires slipping, electric shock, etc. |
LeftTrigger | Underneath the left trigger. |
RightTrigger | Underneath the right trigger. |
LeftHand | On the left side of the controller. |
RightHand | On the right side of the controller. |
Activating Motors
Once you've confirmed that a player's gamepad supports vibration, you can turn on a specific motor with HapticService:SetMotor(). This method takes the gamepad and the amplitude of the vibration as arguments. Amplitude can be any value between 0 and 1.
Activating Motor
local HapticService = game:GetService("HapticService")local gamepad = Enum.UserInputType.Gamepad1local isVibrationSupported = HapticService:IsVibrationSupported(gamepad)if isVibrationSupported thenlocal largeMotor = HapticService:IsMotorSupported(gamepad, Enum.VibrationMotor.Large)if largeMotor thenHapticService:SetMotor(gamepad, Enum.VibrationMotor.Large, 0.5)endend
Controller Emulation
The Controller Emulator lets you accurately emulate gamepad input directly in Studio. The default controller is Generic, and you can select alternatives for Playstation, Xbox, and Quest devices from the upper‑left picker menu.
While playtesting, you can control the experience with the virtual controller using your mouse.
You can also click Edit mappings in the upper‑right corner to view and edit key mappings for the virtual controller, for example E to ButtonL2 or 9 to ButtonA. These mappings are saved like other Studio settings (per controller, per user, per computer) and are translated to gamepad events in both the emulator window and the 3D viewport.