[Client Beta] Introducing PreferredInput and Improved Touch Capabilities

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.

:blue_heart: 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.

263 Likes

This topic was automatically opened after 10 minutes.

I’ve wanted this since BIRTH. I wondered why we werent able to just know the platform without needing to know if they have a keyboard, or if it’s a touchscreen computer.

If there are 100 PerferredInput users, I am 1 of them.
If there is 1 PerferredInput users, I am them.
And if there is no PerferredInput users, then I’m dead.

74 Likes

This is a well thought out feature that cleans up a lot of boilerplate code and will be useful to me and a lot of other developers for their future work. Well done.

11 Likes

Sounds like a great update, however in the wake of Input Action System, is this new API really needed?

5 Likes

Very cool stuff! Super stoked to see cross-platform compatability made easier.

Looking forward to more stuff on this!

6 Likes

Does using a VR headset count as Gamepad?

9 Likes

Literally me same thought… The IAS system would solve this right? like bruh

4 Likes

I’m guessing this is designed to make older codebases that rely on UserInputService instead of InputActions or ContextActionService easier to add cross-platform compatability to? Not sure though. Any tooling to make cross-platform easier to add is good though.

4 Likes

I love how detecting the player’s platform is more simplified!

However, I was hoping this update would enable users to forcefully set their “personal input”, which would allow them to use mixed inputs (ex. using both mouse and gamepad at the same time) without glyphs, inputs, and the player’s current preferred input constantly changing and fighting each other. For example, the new Nintendo Switch 2 Joy-Cons allows for both mouse and gamepad inputs, and with Roblox’s current implementation, that feature would not work. Or, if you were to use remapping software to use the controller’s gyroscope as a mouse in experiences, you would have to also remap all of the controller’s buttons as well, as both mouse and gamepad inputs can’t be used at the same time. Would greatly appreciate if this was considered!

8 Likes

This solves a lot of annoyances with input handling and cross-platform games! I’ll totally be using this.

mouse side buttons when?

4 Likes

And another @sleitnick utility module bites the dust…

25 Likes

IAS is more confusing (at least to me) in my opinion and finding out what platform the user is on can solve more issues than IAS

6 Likes

Using IAS, you also don’t really have full control over inputs.

4 Likes

Yay! I no longer have to use LastInputTypeChanged or GetLastInputType() and can get consistent results without having to check every possible type for a certain input

4 Likes

I’ll take it as a compliment that it’s getting native support!

35 Likes

Does this mean we are ever going to see a full emulator revamp eventually which will allow us to actually simulate mobile inputs properly and properly render mobile UI at the correct resolution & upscaling?

2 Likes

Because no one wants to work with instances when dealing with a fundamentally programmatic feature.

In fact, I’d argue that IAS is worse when it comes to handling preferred input because of how easy it is to screw everything up due to a few instances being misplaced. We have invariants in our code and the object hierarchy now!

10 Likes

This is something the platform has been wanting for a looooong time.
Great to hear that this is beginning to make its way out there.

I will definitely look into taking advantage of it once the feature is fully released so that maintenance for my own projects is minimized.

I wish there was a way I could subscribe to a thread that notifies me on this platform when a Beta feature is marked as fully released.

Suggestion thread regarding beta/production-ready DevForum filters for convenience

6 Likes

There’s a lot of Input-related stuff now, which might be confusing and/or overwhelming to new people.

More under the hood, but here’s the main list:

  • PreferredInput
  • UserInputService
  • ContextActionService
  • InputActionSystem

Each has quirks, of course, but I think there should be a section on the docs with a general overview of them. All on one page I mean. A video on the Roblox Learn channel on YouTube would also be great.

6 Likes