Roblox ships with several different mobile control schemes. A player can choose which control scheme they want to use by changing the mode in the in-game Settings menu. In many cases the nuanced differences between the control schemes don’t matter much to how the game plays and the decision can be left up to the player. However, if you feel one of the schemes suits your game better than the others, you can enforce which controls the player uses. To do this, in StarterPlayer set the DevTouchMovementMode to the scheme you want.
Thumbstick is the default control scheme for Roblox mobile games. It features a virtual thumbstick on the left and jump button on the right. The thumbstick floats, meaning that when the player pushes the stick far enough, the center of the stick will move with the player’s finger. When the player lets go the thumbstick snaps back to the original position.
Thumbstick is a good generic controller. It becomes harder to use if you have lots of GUI elements as the floating thumbstick can move anywhere on the screen. If your screen is mostly empty then this is a good control scheme to use.
DPad is a scheme where all of the movement controls are consolidated into one widget on the left hand side of the screen. Pressing on the outside of the widget moves the character, while pressing the center makes the character jump. While this widget is a little larger than the Thumbstick or Thumbpad controls, it frees the lower right hand corner of the screen for other UI elements.
DPad works well if you need the space normally occupied by the jump button in Thumbstick or Thumbpad. This scheme also works well when jumping isn’t as important in your game and you want the player’s right hand to be able to perform other game actions.
Thumbpad is very similar to the Thumbstick scheme. Movement controls are on the left and a jump button is on the right. The primary difference between Thumbpad and Thumbstick is that the Thumbpad controls do not float.
Thumbpad should be used when you have GUI elements that could potentially be covered by the floating controls of the Thumbstick.
Click to Move
Click to Move does not add any UI elements to the screen by default. Instead, when the player taps on the screen the character tries to reach the touched position. A small sphere will appear where the player taps to give feedback to the player. If a path can be found to the point, the sphere will be white. If there is no valid path, the sphere will flash red.
If the player tries to reach an invalid point more than three times in a row, the Thumbstick control scheme will appear for the player to help them reach the desired point. The Thumbstick controls will disappear the next time the player taps a valid point on the screen.
Since click to move doesn’t normally display any GUI elements, this setup is best when you want to use the screen space for other purposes, or want to keep a simple and clean look for your game. Jumping, however, is harder in Click to move compared with the other controls, and should not be used if jumping is a key mechanic in your game.
Sometimes the standard Roblox control schemes will not work for your game, in which case you should make your own custom controls. The best way to do this is to overwrite the LocalScript named ControlScript that normally gets replicated into a Player instance when the player joins the game.
Example: In this example, we will create custom controls for mobile for a character that is always running. Swiping left or right will make the character strafe left and right. Swiping up will make the character run straight ahead.
In StarterPlayer.StarterPlayerScripts, add two new LocalScripts, one called ‘’ControlScript’’ and one called ‘’CameraScript’’. These will override the default movement and camera controls that Roblox provides.
In the CameraScript, we simply want to Attach the camera behind the character. In the CameraScript, paste the following code:
local Camera = game.Workspace.CurrentCamera local Player = game.Players.LocalPlayer local function OnCharacterAdded(character) wait() Camera.CameraType = Enum.CameraType.Attach Camera.CameraSubject = character:WaitForChild('HumanoidRootPart') end Player.CharacterAdded:connect(OnCharacterAdded)
In the ControlScript we need to do two things. First, we need to make the player character start running forward as soon as it spawns. The Humanoid Move function will be useful for this. The first argument of this function is the direction you want the character to move. The second argument sets whether you want that direction to be relative to the camera or to the world. Since we want the character to run away from the camera, we will set the first argument to Vector3.new(0, 0, -1) and the second argument to true.
We will also be using the Move function to strafe the character. When you use this function to move a character side to side, the character will turn by default. We want the character to strafe in this case, so we will also set AutoRotate to false:
local Player = game.Players.LocalPlayer local function OnCharacterAdded(character) local humanoid = character:WaitForChild('Humanoid') humanoid:Move(Vector3.new(0, 0, -1), true) humanoid.AutoRotate = false end Player.CharacterAdded:connect(OnCharacterAdded)
If we run the game now the character will start running forward without stopping. We need to add a function to move the character when the player swipes on the screen. We will bind the function to the TouchSwipe event.
In the function we will first do some checks to make sure that the character and humanoid exist, just in case the player swipes the screen while the character is spawning. Next, we will move the character based on the direction of the swipe. The TouchSwipe event passes a value from the SwipeDirection enum. Based on which value was passed in, we will move the character in the appropriate direction:
local UserInputService = game:GetService('UserInputService') local function OnSwipe(swipeDirection) local character = Player.Character if not character then return end local humanoid = character:FindFirstChild('Humanoid') if not humanoid then return end if swipeDirection == Enum.SwipeDirection.Up then humanoid:Move(Vector3.new(0, 0, -1), true) elseif swipeDirection == Enum.SwipeDirection.Left then humanoid:Move(Vector3.new(-1, 0, -1), true) elseif swipeDirection == Enum.SwipeDirection.Right then humanoid:Move(Vector3.new(1, 0, -1), true) end end UserInputService.TouchSwipe:connect(OnSwipe)