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:
- Detect connected gamepads to get information on currently connected or disconnected devices.
- Verify valid inputs that are compatible with Roblox.
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.
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:
1local UserInputService = game:GetService("UserInputService")23if UserInputService.GamepadEnabled then4 print("Player has gamepad enabled...")5end6
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:
1local UserInputService = game:GetService("UserInputService")23UserInputService.GamepadConnected:Connect(function(gamepad)4 print("User has connected controller: " .. tostring(gamepad))5end)67UserInputService.GamepadDisconnected:Connect(function(gamepad)8 print("User has disconnected controller: " .. tostring(gamepad))9end)10
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:
1local UserInputService = game:GetService("UserInputService")2if UserInputService:GetGamepadConnected(Enum.UserInputType.Gamepad1) then3 print("Gamepad1 is connected")4elseif UserInputService:GetGamepadConnected(Enum.UserInputType.Gamepad2) then5 print("Gamepad2 is connected")6end7
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:
1local UserInputService = game:GetService("UserInputService")23local availableInputs = UserInputService:GetSupportedGamepadKeyCodes(Enum.UserInputType.Gamepad2)4print("This controller supports the following controls:")5for _, control in pairs(availableInputs) do6 print(control)7end8
There are three ways to receive input from a gamepad:
- Use UserInputService:GetGamepadState() to query all the current input states of gamepad.
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:
1local ContextActionService = game:GetService("ContextActionService")23local function openSpellBook(actionName, inputState, inputObject)4 if inputState == Enum.UserInputState.Begin then5 -- Open spell book6 end7end89ContextActionService:BindAction("OpenSpellBook", openSpellBook, false, Enum.KeyCode.ButtonR2, Enum.KeyCode.B)10
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.
Use the following sample code to listen for an UserInputService.InputBegan event where the A button is pressed on Gamepad1:
1local UserInputService = game:GetService("UserInputService")23UserInputService.InputBegan:Connect(function(input)4 if input.UserInputType == Enum.UserInputType.Gamepad1 then5 if input.KeyCode == Enum.KeyCode.ButtonA then6 print("Button A pressed on Gamepad1")7 end8 end9end)10
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:
1local UserInputService = game:GetService("UserInputService")23local player = game.Players.LocalPlayer4local character = player.Character5if not character or not character.Parent then6 character = player.CharacterAdded:Wait()7end89local leftFoot = character:WaitForChild("LeftFoot")1011-- When leftFoot comes into contact with something, check the gamepad input state12leftFoot.Touched:Connect(function(hit)13 local state = UserInputService:GetGamepadState(Enum.UserInputType.Gamepad1)14 for _, input in pairs(state) do1516 -- If the ButtonR2 is currently held then print out a message17 if input.KeyCode == Enum.KeyCode.ButtonR2 and input.UserInputState == Enum.UserInputState.Begin then18 print("Character's left foot touched something while holding right trigger")19 end20 end21end)22
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:
|A button||Accepts user prompts or GUI selections. Alternatively used for primary actions in an experience, such as jumping.|
|B button||Cancels user prompts or GUI selections. Alternatively used for secondary actions in an experience, such as a dodge, roll, or sprint.|
|Left Thumbstick||Generally associated with character movement.|
|Right Thumbstick||Generally associated with camera movement.|
|Right Trigger||Generally used for primary actions, such as shooting.|
|R1, L1 and X and Y buttons||Secondary actions such as reloading, targeting or accessing an inventory or minimap.|
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:
1local HapticService = game:GetService("HapticService")2local isVibrationSupported = HapticService:IsVibrationSupported(Enum.UserInputType.Gamepad1)3
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:
1local HapticService = game:GetService("HapticService")2local isVibrationSupported = HapticService:IsVibrationSupported(Enum.UserInputType.Gamepad1)3local largeSupported = false4if isVibrationSupported then5 largeSupported = HapticService:IsMotorSupported(Enum.UserInputType.Gamepad1, Enum.VibrationMotor.Large)6end7
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:
1local HapticService = game:GetService("HapticService")2HapticService:SetMotor(Enum.UserInputType.Gamepad1, Enum.VibrationMotor.Large, .5)3
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:
1local HapticService = game:GetService("HapticService")2print(HapticService:GetMotor(Enum.UserInputType.Gamepad1, Enum.VibrationMotor.Large)3
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:
1-- Services2local HapticService = game:GetService("HapticService")3local Players = game:GetService("Players")4local RunService = game:GetService("RunService")56-- Make sure you are running in a LocalScript.7local player = Players.LocalPlayer8assert(player,"This should be running in a LocalScript!")910-- Setup Haptic Feedback Listener11local function updateHapticFeedback()12 -- Check if you currently have a character.13 local character = player.Character14 if character then15 -- Do you have a Humanoid?16 local humanoid = character:FindFirstChildOfClass("Humanoid")17 if humanoid then18 -- Are you in a vehicle seat?19 local seatPart = humanoid.SeatPart20 if seatPart and seatPart:IsA("VehicleSeat") then21 -- Measure the current speed of the vehicle by taking the magnitude of the seat's velocity.22 local speed = seatPart.Velocity.Magnitude2324 -- Measure the current throttle from the user.25 local throttle = math.abs(seatPart.ThrottleFloat)2627 -- Compute how much the controller should be vibrating.28 local vibrationScale = math.min(1, (speed * throttle) / seatPart.MaxSpeed)2930 -- Apply the vibration.31 HapticService:SetMotor(Enum.UserInputType.Gamepad1, Enum.VibrationMotor.Small, vibrationScale)3233 -- Return so the motor doesn't get reset.34 return35 end36 end37 end3839 -- If nothing is happening, turn off the motor.40 HapticService:SetMotor(Enum.UserInputType.Gamepad1, Enum.VibrationMotor.Small, 0)41end4243-- Connect the haptic feedback listener to be updated 60 times a second.44RunService.Heartbeat:Connect(updateHapticFeedback)45