Roblox accepts input commands from USB gamepads such as the Xbox and Playstation controllers. A game can support up to 4 local controllers per client.
You can detect whether a player's device currently has a gamepad active using the GamepadEnabled property. Note that this property merely shows whether or not any gamepads are connected, it does not specify how many are plugged in or which slots they are in.
if game:GetService("UserInputService").GamepadEnabled then print("Player has gamepad enabled") end
Since up to four controllers can be connected to a client at once, it is important to know which gamepads are active. One way to do this is to listen to the GamepadConnected and GamepadDisconnected events. These events will fire when a device is enabled or disabled respectively, and both will pass an UserInputType enum to the connected function indicating which gamepad caused the event. In most cases the controller will be Enum.UserInputType.Gamepad1 but if your game supports local multiplayer then you will have to check.
local UIS = game:GetService("UserInputService") UIS.GamepadConnected:connect(function(gamepad) print("Player has plugged in controller: " .. tostring(gamepad)) end) UIS.GamepadDisconnected:connect(function(gamepad) print("Player has unplugged in controller: " .. tostring(gamepad)) end)
You can also actively query whether a particular controller is connected using the GetGamepadConnected function. This function takes an UserInputType enum as an argument and will only work with the values of Gamepad1 through Gamepad4.
if game:GetService("UserInputService"):GetGamepadConnected(Enum.UserInputType.Gamepad1) then print("Gamepad1 is connected") end
There are three ways to get input from a controller. A straightforward way is to listen for events in UserInputService. If you plan on allowing a variety of control schemes for various inputs you can use ContextActionService. Lastly, you can query the state of all of a controller's input with the GetGamepadState function.
All of the buttons on a gamepad will fire the InputBegan and InputEnded events. The passed in InputObject will contain which controller fired the event in the UserInputType property. The specific button or stick that fired the event will be in the KeyCode property.
game:GetService("UserInputService").InputBegan:connect(function(input) if input.UserInputType == Enum.UserInputType.Gamepad1 then if input.KeyCode == Enum.KeyCode.ButtonA then character.Humanoid.Jump = true end end end)
Some gamepads support analog controls. To get input from these controls, the InputChanged function can be used. Note that Roblox only supports analog thumbsticks and trigger buttons (L2 and R2). In the Changed event the position of the input's axis can be read in the Position. The thumbsticks position will always be on the X Y axes between the values of -1 to 1 for both axes. The trigger buttons will only have values between 0 and 1 on the Z axis: 0 at its starting position, 1 when fully depressed.
game:GetService("UserInputService").InputChanged:connect(function(input, processed) if input.UserInputType == Enum.UserInputType.Gamepad1 then if input.KeyCode == Enum.KeyCode.Thumbstick1 then character.Humanoid:Move(Vector3.new(input.Position.X, 0, -input.Position.Y), true) end end end)
You can bind functions to input from a gamepad using ContextActionService. This is particularly useful if you want to bind controls both to a gamepad and to other inputs (such as keyboard or touch controls). For example, suppose you want to bind a custom control to jump in your game. In this case, say the player can jump if either they press the A button on a gamepad or if they press the "F" key on their keyboard. ContextActionService can handle both cases in one function:
local function jumpFunction(actionName, state, inputObject) game.Players.LocalPlayer.Character.Humanoid.Jump = true end game:GetService("ContextActionService"):BindActionToInputTypes("Jump", jumpFunction, false, "f", Enum.KeyCode.ButtonA)
Keep in mind that ContextActionService bound functions will fire on all input events: Began, Changed, and Ended. In the bound function it is recommended to check the UserInputState so the desired action only happens on the state you intend it to:
local function printFunction(actionName, state, inputObject) if state == Enum.UserInputState.Begin then print("I only print on the begin event") end print("I print on every event!") end game:GetService("ContextActionService"):BindActionToInputTypes("Print", printFunction, false, "p", Enum.KeyCode.ButtonB)
Gamepad input state
The state of all the buttons and sticks on a gamepad can be gotten at any time with the GetGamepadState. This can be useful for events in your game when something happens to your player and you want to check to see if that player is holding down an input. For example, the following code will detect when a character's left leg touches something while the player is holding down the A button:
local player = game.Players.LocalPlayer while not player.Character do wait() end local character = player.Character local userInputService = game:GetService("UserInputService") character["Left Leg"].Touched:connect(function(hit) local state = userInputService:GetGamepadState(Enum.UserInputType.Gamepad1) for _, input in pairs(state) do if input.KeyCode == Enum.KeyCode.ButtonA and input.UserInputState == Enum.UserInputState.Begin then print("I stepped on something while holding A") end end end)
Since Roblox supports a generic USB gamepad, many different types of controllers can be used. Not all controllers have the same number of inputs and so it is important to check which inputs a connected controller has. If your game relies on the left analog stick for control it is important to make sure the player's controller actually has one! You can check what inputs a given controller supports with the GetSupportedGamepadKeyCodes function. This function takes an UserInputType enum as an argument, expecting the values of Gamepad1 through Gamepad4. This function returns a table with a list of all the available inputs for the specified controller. Note that the Start and Select buttons are being used internally by Roblox by default.
local availableInputs = game:GetService("UserInputService"):GetSupportedGamepadKeyCodes(Enum.UserInputType.Gamepad2) print("This controller supports the following controls:") for _, control in pairs(availableInputs) do print(control) end
You can also check to see if a gamepad supports a specific button with the GamepadSupports function.
This example binds character controls to the gamepad. The left thumbstick controls movement, the right thumbstick controls the camera, the A button makes the character jump, and R1 toggles increased runspeed.
-- Make variables for services local userInputService = game:GetService("UserInputService") local runService = game:GetService("RunService") -- Make variables for player, character, and camera local player = game.Players.LocalPlayer while not player.Character do wait() end local character = player.Character local camera = game.Workspace.CurrentCamera -- Update camera rotation every render frame local currentAngle = 0 local deltaAngle = 0 runService.RenderStepped:connect(function() currentAngle = currentAngle + deltaAngle camera.CoordinateFrame = CFrame.new(character.Head.Position) * CFrame.Angles(0, math.rad(currentAngle), 0) * CFrame.new(0, 0, 10) end) -- Check for change event in input. Used for thumbstick input as those are analog userInputService.InputChanged:connect(function(input, processed) if input.UserInputType == Enum.UserInputType.Gamepad1 then -- Check left thumbstick and move character on change if input.KeyCode == Enum.KeyCode.Thumbstick1 then character.Humanoid:Move(Vector3.new(input.Position.X, 0, -input.Position.Y), true) end -- Check right thumbstick and change camera angle on change if input.KeyCode == Enum.KeyCode.Thumbstick2 then deltaAngle = input.Position.X * 5 end end end) -- Check for user input ended events. Handles release of R1 and thumbsticks userInputService.InputEnded:connect(function(input, processed) if input.UserInputType == Enum.UserInputType.Gamepad1 then -- Stop moving character if left thumbstick released if input.KeyCode == Enum.KeyCode.Thumbstick1 then character.Humanoid:Move(Vector3.new(0,0,0)) end -- Stop moving camera if right thumbstick released if input.KeyCode == Enum.KeyCode.Thumbstick2 then deltaAngle = 0 end -- Make character move at normal speed if R1 is released if input.KeyCode == Enum.KeyCode.ButtonR1 then character.Humanoid.WalkSpeed = 16 end end end) -- Check for user input began events. Handles jumping and increasing speed userInputService.InputBegan:connect(function(input, processed) if input.UserInputType == Enum.UserInputType.Gamepad1 then -- If A button is pressed then make the character jump if input.KeyCode == Enum.KeyCode.ButtonA then character.Humanoid.Jump = true end -- If R1 is pressed then make the character move faster if input.KeyCode == Enum.KeyCode.ButtonR1 then character.Humanoid.WalkSpeed = 30 end end end)
Roblox by default ships a control scheme for gamepads connected to computers, tablets and mobile devices so you can control the standard Roblox character and camera with a gamepad. In your game you can inspect this code by doing the following:
- Open a new or saved place in Roblox Studio
- Click Play Solo or press F5.
- In the Explorer, open StarterPlayer. Under StarterPlayer there should be two scripts, CameraScript and ControlScript. Here is what they look like with all the children scripts.
The default gamepad control script is found in StarterPlayerScripts.ControlScript.MasterControl.Gamepad. This is a good script to start with if you are interested in creating your own gamepad control scheme, or want to get ideas about ways to do gamepad controls. If you copy these scripts and press the Stop button in studio, you can paste them back into StarterPlayerScripts and override the default control schemes. Note: this script only does character movement, if you are interested in learning about camera movement look at StarterPlayerScripts.CameraScript.RootCamera.
As with any method of user input, it is best to have some consistencies across different games and applications. This ensures the user can immediately feel familiar and comfortable with your control scheme. Below are some suggested practices when implementing any gamepad controls.
- If you implement any user prompts/GUI selection, pressing the A button should be the accept button
- Any GUI or any state that is modal should be able to be cancelled by pressing the B button.
- Hints on screen for what button does what are helpful, especially when using a complicated GUI (Ex: Inventory GUIs, Trade GUIs, Dialog Systems, etc.)
- Character movement should be tied the left thumbstick.
- Camera movement should be tied to the right thumbstick.
- Primary actions usually happen with the right trigger (R2) or the A button
- Secondary actions usually happen with the left trigger (L2) or the R1 and L1 buttons. If tying a secondary action to a face button, X button and Y buttons are good choices.
- Left thumbstick and DPad should both be able to move the GUI selection around.
- Allowing the user to remap buttons can make your game much more accessible.