Gamepad

Roblox accepts input from USB gamepads such as Xbox and PlayStation controllers. Since gamepads can come in different varieties, you need to follow additional setup to verify that a user's gamepad inputs are usable in your experience.

To set up gamepad inputs, you can use UserInputService to perform the following:

When binding gamepad inputs, see common control schemas to create a consistent gamepad experience between experiences.

After your inputs are set, you can additionally customize your gamepads by including vibration feedback on supported controllers. See Haptic Feedback for instructions on verifying and activating vibrations.

Detecting Gamepads

You can detect whether a user's device currently has a gamepad active using the UserInputService.GamepadEnabled property.

Use the following sample code to print out a console message if the GamepadEnabled property is true:


local UserInputService = game:GetService("UserInputService")
if UserInputService.GamepadEnabled then
print("Player has gamepad enabled...")
end

You can connect up to eight local gamepads to a client at once. You can check for connected gamepads with GamepadConnected and GamepadDisconnected events. These events will fire when a device is connected or disconnected respectively. Both events will pass a UserInputType to the connected function indicating which gamepad caused the event. In most cases, the connected gamepad is UserInputType.Gamepad1.

Use the following code sample to print out the specific gamepad that is connected and disconnected:


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() function. This takes a UserInputType as an argument and only accepts values of UserInputType.Gamepad1 through UserInputType.Gamepad8.

Use the following code sample to check for a specific gamepad and print a message if it is connected:


local UserInputService = game:GetService("UserInputService")
if UserInputService:GetGamepadConnected(Enum.UserInputType.Gamepad1) then
print("Gamepad1 is connected")
elseif UserInputService:GetGamepadConnected(Enum.UserInputType.Gamepad2) then
print("Gamepad2 is connected")
end

Verifying Supported Inputs

Since gamepads can have different sets of inputs, check which inputs are supported with UserInputService:GetSupportedGamepadKeyCodes(). This function takes a UserInputType as an argument and returns a table with a list of all available inputs for the specified controller.

Use the following code sample to print out a list of available inputs detected from Gamepad 2:


local UserInputService = game:GetService("UserInputService")
local availableInputs = UserInputService:GetSupportedGamepadKeyCodes(Enum.UserInputType.Gamepad2)
print("This controller supports the following controls:")
for _, control in pairs(availableInputs) do
print(control)
end

Receiving Input

There are three ways to receive input from a gamepad:

ContextActionService

You can use ContextActionService for binding controls to both gamepads and other input sources such as mobile touchscreen buttons or binding multiple functions to a single button input on any device. For example, use ContextActionService to bind an OpenSpellBook action to the right trigger (R2) on a gamepad and the B key on a keyboard in one function.

Use the following code sample to bind an OpenSpellBook action to the gamepad's R2 button and the B key on the keyboard:


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)

UserInputService

You can use UserInputService to bind controls directly from a gamepad. When detecting gamepad events with UserInputService, use UserInputService.InputBegan to detect when the button was initially pressed and UserInputService.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.

Use the following sample code to listen for an UserInputService.InputBegan event where the A button is pressed on Gamepad1:


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 Input State

You can detect the current state of all buttons and sticks on a gamepad with the UserInputService:GetGamepadState() function. This is useful if you need to check the current gamepad inputs when a distinct event occurs in your experience. For example, you may want to check if specific buttons are being pressed when a character touches an object.

Use the following code sample to detect if the Gamepad1 R2 button is being held when the player character's left foot comes contacts a surface:


local Players = game:GetService("Players")
local UserInputService = game:GetService("UserInputService")
local player = Players.LocalPlayer
local character = player.Character
if not character or not character.Parent then
character = player.CharacterAdded:Wait()
end
local leftFoot = character:WaitForChild("LeftFoot")
-- When leftFoot 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 pairs(state) do
-- If the ButtonR2 is currently held then 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)

Common Control Schemas

Gamepads come in a variety of shapes and sizes. As with any method of user input, it's best to create some consistency across different games and applications.

The following are common input binds that will help users immediately feel familiar and comfortable with the gamepad controls:

InputCommon Use-cases
A buttonAccepts user prompts or GUI selections. Alternatively used for primary actions in an experience, such as jumping.
B buttonCancels user prompts or GUI selections. Alternatively used for secondary actions in an experience, such as a dodge, roll, or sprint.
Left ThumbstickGenerally associated with character movement.
Right ThumbstickGenerally associated with camera movement.
Right TriggerGenerally used for primary actions, such as shooting.
R1, L1 and X and Y buttonsSecondary actions such as reloading, targeting or accessing an inventory or minimap.

Haptic Feedback

Many gamepad controllers, such as Xbox One controllers, have motors built in to provide haptic feedback. Adding rumbles and vibrations can greatly enhance a user's experience and provide subtle feedback beyond visuals or audio. You can use the HapticService to verify vibration support before turning on the controller motors.

Checking for Vibration Support

Not all controllers support vibration so it is important to check if the plugged-in controllers have support before attempting to use the controller motors. To check if a given controller has rumble support at all, you can call HapticService:IsVibrationSupported().

Use the following sample code to verify if vibration is supported on gamepad 1:


local HapticService = game:GetService("HapticService")
local isVibrationSupported = HapticService:IsVibrationSupported(Enum.UserInputType.Gamepad1)

Some controllers have multiple motors for various scales of vibration. Once you have checked if a gamepad supports vibration, you should also check if it supports the motors you intend to use. The Xbox One controller has 4 motors:

  • Large: in the left side of the controller. Good for generic rumble.
  • Small: in the right side of the controller. Good for more subtle rumbles(tire slipping, electric shock, etc.).
  • Left Trigger: underneath the left trigger. Good for braking, gun reloading, etc.
  • Right Trigger: underneath the right trigger. Good for recoil, acceleration, etc.

The user might not have a controller that supports all of these motors. Many only support the Large and Small motors (no triggers). You can use HapticService:IsMotorSupported() to see if the user's controller supports the motor you want to use.

Use the following sample code to verify if large vibration motors are supported on gamepad 1:


local HapticService = game:GetService("HapticService")
local isVibrationSupported = HapticService:IsVibrationSupported(Enum.UserInputType.Gamepad1)
local largeSupported = false
if isVibrationSupported then
largeSupported = HapticService:IsMotorSupported(Enum.UserInputType.Gamepad1, Enum.VibrationMotor.Large)
end

Turning on Motors

Once you have confirmed that a user's gamepad supports vibration you can start using the gamepad motors. You can use HapticService:SetMotor() to turn on a specific motor on a gamepad. This function takes the gamepad and the amplitude of the vibration as arguments. The amplitude can be any value between 0 and 1.

The following sample code sets the amplitude for gamepad 1's large motor to .5:


local HapticService = game:GetService("HapticService")
HapticService:SetMotor(Enum.UserInputType.Gamepad1, Enum.VibrationMotor.Large, .5)

You can also use HapticService:GetMotor() to get the current vibration amplitude of a given motor. Use the following code sample to print the current amplitude for gamepad 1's large motor:


local HapticService = game:GetService("HapticService")
print(HapticService:GetMotor(Enum.UserInputType.Gamepad1, Enum.VibrationMotor.Large)

The following code is a sample implementation of vibration when a user character gets into a vehicle, where the vibration is based on the throttle of the vehicle:


-- Services
local HapticService = game:GetService("HapticService")
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
-- Make sure you are running in a LocalScript.
local player = Players.LocalPlayer
assert(player,"This should be running in a LocalScript!")
-- Setup Haptic Feedback Listener
local function updateHapticFeedback()
-- Check if you currently have a character.
local character = player.Character
if character then
-- Do you have a Humanoid?
local humanoid = character:FindFirstChildOfClass("Humanoid")
if humanoid then
-- Are you in a vehicle seat?
local seatPart = humanoid.SeatPart
if seatPart and seatPart:IsA("VehicleSeat") then
-- Measure the current speed of the vehicle by taking the magnitude of the seat's velocity.
local speed = seatPart.Velocity.Magnitude
-- Measure the current throttle from the user.
local throttle = math.abs(seatPart.ThrottleFloat)
-- Compute how much the controller should be vibrating.
local vibrationScale = math.min(1, (speed * throttle) / seatPart.MaxSpeed)
-- Apply the vibration.
HapticService:SetMotor(Enum.UserInputType.Gamepad1, Enum.VibrationMotor.Small, vibrationScale)
-- Return so the motor doesn't get reset.
return
end
end
end
-- If nothing is happening, turn off the motor.
HapticService:SetMotor(Enum.UserInputType.Gamepad1, Enum.VibrationMotor.Small, 0)
end
-- Connect the haptic feedback listener to be updated 60 times a second.
RunService.Heartbeat:Connect(updateHapticFeedback)