We use cookies on this site to enhance your user experience

Cross-Platform Development

Cross-Platform Development

Oct 09 2019, 11:05 AM PST 10 min

This article outlines best practices for Roblox game development across multiple platforms.

Roblox Philosophy

Unlike some game engines, Roblox is inherently cross-platform players can discover and play games on a PC, then later pick up their phone and continue playing where they left off. In most cases, Roblox games should be accessible and enjoyable on all platforms, versus being optimized for one platform and just “basically functional” on others.

Mobile First

Recent stats cite that over 55% of Roblox game sessions are on mobile, so you should focus a proportionate effort on building a great mobile experience. When planning your UI and controls, consider the following:

UI Layout

Just because a GUI fits perfectly on a PC screen doesn’t mean it’s as functional on a smaller mobile screen. For example, the color customization tiles in this GUI become small and cramped on a phone:

In contrast, a slight redesign of the GUI offers a positive user experience on both PC and phone:

Reserved Regions

On mobile devices, the /articles/customizing game controls#mobile-controls|default controls occupy a portion of the bottom-left and/or bottom-right corners of the screen. When you design the game UI, avoid placing important info or virtual buttons in these regions.

Thumb Zones

Most mobile players use two thumbs — one on the virtual thumbstick/DPad and one on the jump button. Depending on the physical size of the device and the player’s hands, “reaching” too far from the bottom corners becomes uncomfortable or impossible, so you should avoid placing frequently-used buttons outside of the green zones.

Adaptable UI

Comfortable thumb zones differ between phones and tablets since tablets have a larger screen. Remember that a button placed 30% below the screen’s top edge is easily reachable on a phone but almost unreachable on a tablet.

A more reliable way to position custom buttons is in direct relation to the jump button. The following code fetches the position of the jump button and creates a placeholder ImageButton above it:

-- Get reference to player's jump button
local player = game.Players.LocalPlayer
local PlayerGui = player:WaitForChild("PlayerGui")
local ScreenGui = PlayerGui:WaitForChild("ScreenGui")
local TouchGui = PlayerGui:WaitForChild("TouchGui")
local TouchControlFrame = TouchGui:WaitForChild("TouchControlFrame")
local JumpButton = TouchControlFrame:WaitForChild("JumpButton")

-- Get absolute size and position of button
local absSizeX, absSizeY = JumpButton.AbsoluteSize.X, JumpButton.AbsoluteSize.Y
local absPositionX, absPositionY = JumpButton.AbsolutePosition.X, JumpButton.AbsolutePosition.Y

-- Create new button above jump button
local customButton = Instance.new("ImageButton")
customButton.Parent = ScreenGui
customButton.AnchorPoint = Vector2.new(0.5, 1)
customButton.Size = UDim2.new(0, absSizeX*0.8, 0, absSizeY*0.8)
customButton.Position = UDim2.new(0, absPositionX+(absSizeX/2), 0, absPositionY-20)

Context-Based UI

Screen space is considerably smaller on mobile devices, so you should show only the most vital information during active gameplay. For example, if there’s a special player action to open doors, it doesn’t make sense to constantly show an “Open Door” button — instead, the button should appear only when the player is near a door and disappear when they’ve moved a certain distance away.

Input Detection

In some cases, it’s necessary to know the player’s current device in order to adjust the UI, show action buttons/reminders, etc. For instance, if a player approaches a treasure chest and there’s an action bound to collecting the gold, you may want to show PC players an on-screen T key icon but show mobile players an active “Collect” button.

Mobile — Active Collect button
PC — T key reminder

The following ModuleScript, placed within ReplicatedStorage and renamed to PlayerInputModule, can be used to fetch the player’s input type, after which you can adapt the UI layout or context as suggested above.

local UserInputService = game:GetService("UserInputService")

local PlayerInput = {}

local inputTypeString
-- If device has active keyboard and mouse, assume those inputs
if UserInputService.KeyboardEnabled and UserInputService.MouseEnabled then
	inputTypeString = "Keyboard/Mouse"
-- Else if device has touch capability but no keyboard and mouse, assume touch input
elseif UserInputService.TouchEnabled then
	inputTypeString = "Touch"
-- Else if device has an active gamepad, assume gamepad input
elseif UserInputService.GamepadEnabled then
	inputTypeString = "Gamepad"

function PlayerInput.getInputType()
	local lastInputEnum = UserInputService:GetLastInputType()

	if lastInputEnum == Enum.UserInputType.Keyboard or string.find(tostring(lastInputEnum.Name), "MouseButton") or lastInputEnum == Enum.UserInputType.MouseWheel then
		inputTypeString = "Keyboard/Mouse"
	elseif lastInputEnum == Enum.UserInputType.Touch then
		inputTypeString = "Touch"
	elseif string.find(tostring(lastInputEnum.Name), "Gamepad") then
		inputTypeString = "Gamepad"
	return inputTypeString, lastInputEnum

return PlayerInput

Once the PlayerInputModule script is in place, you can get the player’s last input type from a LocalScript as follows:

local ReplicatedStorage = game:GetService("ReplicatedStorage")

-- Require module
local PlayerInputModule = require(ReplicatedStorage:WaitForChild("PlayerInputModule"))

local currentPlayerInput, inputEnum = PlayerInputModule.getInputType()
print(currentPlayerInput, inputEnum)
  • cross-platform
  • mobile
  • gui