Hi Creators!
TL;DR
- We’re releasing a new API today into client beta: PreferredInput. This adaptive property makes it easier to build cross-platform input behavior by exposing the primary input type available to a player, which is especially useful if they have multiple input devices available for use. Whether they’re on a gamepad, touchscreen, or keyboard, PreferredInput is your new go-to for handling button prompts and input labels, UI modes, and device-specific interactions. You can publish PreferredInput in your experience today.
- Next week, we’ll be rolling out improvements to how input is detected across devices, including a fix for which devices are reported as TouchEnabled and improvements to touch & gesture capabilities. If you use TouchEnabled to determine when to display mobile-based UI or touch controls, we want to highlight how this update might impact you & share how PreferredInput can help, especially for experiences that run on mixed input devices.
How to Use PreferredInput
The value of PreferredInput changes based on the value of legacy UserInputService properties such as KeyboardEnabled, GamepadEnabled, and TouchEnabled, as well as the player’s most recent interaction with a connected gamepad or keyboard/mouse to provide a reliable default view of how a player is interacting with your experience. There are three items in the PreferredInput enum:
- KeyboardAndMouse: The player has connected or most recently interacted with a keyboard or mouse. Note that PreferredInput remembers the players’ last configuration when they start the client.
- Gamepad: The player has connected or most recently interacted with a gamepad.
- Touch: The player’s device has touch capability and no other input schema is available or connected.
We recommend you to use PreferredInput when:
- You have different hotkeys or button prompts per input type
- You want to switch UI layouts based on input (e.g., touch buttons vs. keyboard UI)
- You want to reduce noisy UI switching on devices with mixed input devices
Here’s an example of how you could use PreferredInput in your experience:
local UserInputService = game:GetService("UserInputService")
local image = script.Parent
local function PreferredInputChanged()
local preferredInput = UserInputService.PreferredInput
if preferredInput == Enum.PreferredInput.Touch then
image.Image = "rbxassetid://2716591855"
elseif preferredInput == Enum.PreferredInput.Gamepad then
local mappedIconImage = UserInputService:GetImageForKeyCode(Enum.KeyCode.ButtonA)
image.Image = mappedIconImage
else -- Enum.PreferredInput.KeyboardAndMouse
image.Image = "rbxasset://textures/ui/Controls/key_single.png"
end
end
PreferredInputChanged()
UserInputService:GetPropertyChangedSignal("PreferredInput"):Connect(function()
PreferredInputChanged()
end)
The code chunk above would replace the following code chunk:
See Code Chunk
local UserInputService = game:GetService("UserInputService")
local inputTypeStringValue = Instance.new("StringValue")
inputTypeStringValue.Parent = script.Parent
-- If device has active keyboard and mouse, assume those inputs
if UserInputService.KeyboardEnabled and UserInputService.MouseEnabled then
inputTypeStringValue.Value = "Keyboard/Mouse"
-- Else if device has touch capability but no keyboard and mouse, assume touch input
elseif UserInputService.TouchEnabled then
inputTypeStringValue.Value = "Touch"
-- Else if device has an active gamepad, assume gamepad input
elseif UserInputService.GamepadEnabled then
inputTypeStringValue.Value = "Gamepad"
end
UserInputService.LastInputTypeChanged:Connect(function(lastInputType)
if lastInputType == Enum.UserInputType.Keyboard or string.find(tostring(lastInputType.Name), "MouseButton") or lastInputType == Enum.UserInputType.MouseWheel then
inputTypeStringValue.Value = "Keyboard/Mouse"
elseif lastInputType == Enum.UserInputType.Touch then
inputTypeStringValue.Value = "Touch"
elseif string.find(tostring(lastInputType.Name), "Gamepad") then
inputTypeStringValue.Value = "Gamepad"
end
end)
local image = script.Parent
local function InputTypeChanged()
if inputTypeStringValue.Value == "Touch" then
image.Image = "rbxassetid://2716591855"
elseif inputTypeStringValue.Value == "Gamepad" then
local mappedIconImage = UserInputService:GetImageForKeyCode(Enum.KeyCode.ButtonA)
image.Image = mappedIconImage
else -- "Keyboard/Mouse"
image.Image = "rbxasset://textures/ui/Controls/key_single.png"
end
end
InputTypeChanged()
inputTypeStringValue:GetPropertyChangedSignal("Value"):Connect(InputTypeChanged)
When should I use LastInputType or UserInputService.XEnabled?
KeyboardEnabled/GamepadEnabled/TouchEnabled and LastInputType will not be deprecated – and they’re useful when you need more detailed information about player input. But when you want to build for flexibility and adapt to a player’s current input scheme, PreferredInput is your best out-of-the-box tool.
Upcoming Changes
Next week, we will be patching fixes to TouchEnabled so that any device with a touch input surface will now correctly return TouchEnabled = true. This change should primarily impact Windows devices; previously, certain platforms like touch-enabled Windows laptops and handheld PCs were incorrectly reporting TouchEnabled = false.
PreferredInput is available for use starting today. We will update this post when the Touch updates have rolled out.
What do you need to do?
- If you use TouchEnabled to determine input availability, no changes are needed — this update just fixes inconsistencies.
- If you use TouchEnabled to determine which UI elements to show, we recommend switching to PreferredInput. It’s more robust for cross-platform design and avoids false positives on hybrid devices.
Made with love
Special thanks to @crypto_mancer, @PotionSeller33, @LittleEel0621, @Paragraph3232, and @MetaVars for their hard work in making this happen! Let us know if you have any questions.