We use cookies on this site to enhance your user experience

Creating Mobile Buttons

Creating Mobile Buttons

Jun 14 2019, 2:11 PM PST 10 min

Porting games from a PC environment to a mobile environment can be difficult, especially when it comes to input. A computer has a wealth of input from the keyboard to the mouse, whereas a mobile device, such as an iPad only has touch. One solution is to use the ContextActionService. This service allows you to bind a function to traditional PC input and at the same time creates an on screen button only visible on a mobile device.

Additionally, mobile screen space is at a premium, and sometimes it is desirable for on screen buttons to only show when relevant. For example, let’s say your game has doors and there is a special player action to open a door. It doesn’t make sense to show an “Open Door” button all game long. Instead, the button should only show when the player is near a door, and should disappear when the player has moved a distance away. Even in a PC game, sometimes it makes sense for a certain key to perform an action under specific circumstances and not in others. ContextActionService allows for very quick and easy manipulation of when input is tied to functions, as well as when mobile action buttons are shown or not.

Using ContextActionService

To use the ContextActionService first a reference has to be declared in a LocalScript. This service will not work in a Server Script as the server does not handle input from players.

local contextAction = Game:GetService("ContextActionService")

Adding Mobile Buttons (Bind)

After the ContextActionService has been declared, the ContextActionService/BindAction function can be used. This function will associate specified input with the function that should be called when the input is entered. This function will also display a mobile button if desired. This function takes several parameters:

void ContextActionService:BindAction(
    string actionName,
    function functionToBind,
    bool createTouchButton,
    Tuple inputTypes

This string is a key used by other functions in ContextActionService to manipulate the binding.

This is the function you want to be called when the specified input is triggered. This function can be defined earlier in the script or can be defined inline. This function will be called with three arguments: a string that is the actionName that is calling this function, a Enum/UserInputState that defines the state the input was in when it called the function, and lastly the InputObject that caused the call to the function.

This boolean indicates whether or not you want a button to be created when your game is running on a mobile device. If you are using this service just to bind input for PC controls, then you can set this to false. Otherwise this should be true if you want a button when your game is played on a mobile device.

This tuple contains all of the input you want to bind to the function. This tuple can contain values from Enum/KeyCode, Enum/UserInputType, or simple strings corresponding to keys on a keyboard.

game:GetService("ContextActionService"):BindAction("OpenDoorBinding", openDoorFunc, true, "o")

Removing Mobile Buttons (Unbind)

When you no longer want input tied to a function, or if you want to remove an mobile button from the screen, use ContextActionService/UnbindAction. This function takes a string as an argument which is the key defined in ContextActionService/BindAction. You can also use ContextActionService/UnbindAllActions to remove all functions that have been bound.


Modifying Buttons

ContextActionService provides several functions to manipulate the buttons that are generated by binding functions. A button can use a custom image, much like an ImageLabel by using ContextActionService/SetImage and providing the name of the binding and the url of the image.

The button can also be positioned using ContextActionService/SetPosition and providing the name of the binding and the UDim2 where you want the button to be positioned. If you do not specify this the button will appear near the jump button on the right hand side of the screen.


In this game there is a teleport pad that can take a player to the destination when they step on it. In this case, we won’t actually teleport until the user presses a button. We could make a new GUI element for this button, but we only want the button to appear when the user is on the teleporter. Using ContextActionService, we can bind a teleport function to a button when the player is in the right spot which will show the button, and then unbind it when the player leaves which will remove the button. Note this button will only show up on mobile devices. To test on a PC or Mac we will also bind the “t” key on the keyboard to the action:

-- Make variables for the local player and ContextActionService
local player = game.Players.LocalPlayer
local ContextActionService = game:GetService("ContextActionService")

-- Define teleport function which we will bind to a button
function teleportPlayer(actionName, actionInputState, actionInputObject)
	player.Character.Torso.CFrame = game.Workspace.DestinationPad.CFrame + Vector3.new(0, 4, 0)
	-- Remove binding to hide button after teleport

-- Setup Touched and TouchEnded events. Also making a boolean to keep track of whether we have bound the function or not.
local playerOnPad = false
	if part and part.Parent == player.Character then
		if not playerOnPad then
			ContextActionService:BindAction("teleport", teleportPlayer, true, "t")
		playerOnPad = true

	if part and part.Parent == player.Character then
		if playerOnPad then
		playerOnPad = false

Working with Gamepads

ContextActionService also provides an easy way to support Gamepad context actions in your game. It works the same way as any input, so something like this:

--actionName will be a string that corresponds to the name the action was given (in this case "openDoor")
--actionInputState will be the Enum.UserInputState that the input was in when this function was called
--actionInputObject will be the inputObject that called this function
local openDoorFunction = function(actionName, actionInputState, actionInputObject)
     if actionInputState == Enum.UserInputState.Begin and actionInputObject.UserInputType == Enum.UserInputType.Gamepad1 then

game:GetService("ContextActionService"):BindAction("openDoor", openDoorFunction, false, Enum.KeyCode.ButtonX)

Will make any time ButtonX is pressed or released call the function openDoorFunction. It is important to note that this will be called for all gamepads, so you should check and make sure the gamepad calling it is the one you want.

Overriding Inputs

Suppose I have code like this:

game:GetService("ContextActionService"):BindAction("openDoor", openDoorFunction, false, Enum.KeyCode.ButtonX)
game:GetService("ContextActionService"):BindAction("changeTool, changeToolFunction, false, Enum.KeyCode.ButtonX)

What happens when I press ButtonX?
The changeToolFunction will be called, and the openDoorFunction will NOT be called. This is because changeToolFunction was bound last, so it takes precedence. If the changeTool action was unbound later, then the openDoor action will be called for ButtonX in the future.

What happens the moment I bind an input that is already bound?
The currently bound function is called, but with a special UserInputState called Enum/UserInputState/Cancel. This is to allow the currently bound function to do any clean up it might want to do (Ex: you have Enum/KeyCode/Thumbstick1 bound to controlling the character, but you bind a menu action to thumbstick1 over that action. The character movement function will receive a cancel event so it can stop the character if it is currently moving.) If the latter bound function unbinds itself later, the original bound function will be called with Enum/UserInputState/End indicating that the original bound function can resume handling input.

  • service
  • mobile