I think an API that returns the user’s device type (i.e. PC, Xbox, etc.) would be awesome.
Get ready for 666 everybody!! Watch out for Devilblox!
exception while signaling: Debugger can be attached to a script or module script
Everyone has been asking for this for years, but we never got it.
This is what I did (requires FastSignal - A consistent signal library):
--< Services >--
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local RunService = game:GetService("RunService")
local UserInputService = game:GetService("UserInputService")
--< Assets >--
local Modules = ReplicatedStorage.Modules
local Components = Modules.Components
--< Components >--
local Signal = require(Components.FastSignal)
--< Constants >--
local COMPUTER_INPUTS = {
Enum.UserInputType.MouseButton1,
Enum.UserInputType.MouseButton2,
Enum.UserInputType.MouseButton3,
Enum.UserInputType.MouseWheel,
Enum.UserInputType.MouseMovement,
Enum.UserInputType.Keyboard
}
local GAMEPAD_INPUTS = {
Enum.UserInputType.Gamepad1,
Enum.UserInputType.Gamepad2,
Enum.UserInputType.Gamepad3,
Enum.UserInputType.Gamepad4,
Enum.UserInputType.Gamepad5,
Enum.UserInputType.Gamepad6,
Enum.UserInputType.Gamepad7,
Enum.UserInputType.Gamepad8
}
local TOUCH_INPUTS = {
Enum.UserInputType.Touch,
Enum.UserInputType.Gyro,
Enum.UserInputType.Accelerometer
}
--< Controller >--
local Controller = {}
Controller.Computer = false :: boolean
Controller.ComputerChanged = Signal.new() :: Signal.ScriptSignal<boolean>
Controller.Console = false :: boolean
Controller.ConsoleChanged = Signal.new() :: Signal.ScriptSignal<boolean>
Controller.Mobile = false :: boolean
Controller.MobileChanged = Signal.new() :: Signal.ScriptSignal<boolean>
function Controller.Start()
UserInputService.LastInputTypeChanged:Connect(Controller.LastInputTypeChanged)
Controller.LastInputTypeChanged(UserInputService:GetLastInputType())
UserInputService.InputChanged:Connect(function(Input)
Controller.LastInputTypeChanged(Input.UserInputType)
end)
UserInputService.InputBegan:Connect(function(Input)
Controller.LastInputTypeChanged(Input.UserInputType)
end)
UserInputService.InputEnded:Connect(function(Input)
Controller.LastInputTypeChanged(Input.UserInputType)
end)
end
function Controller.LastInputTypeChanged(Input: Enum.UserInputType)
local OnComputer = table.find(COMPUTER_INPUTS, Input) ~= nil
local OnConsole = table.find(GAMEPAD_INPUTS, Input) ~= nil
local OnMobile =
table.find(TOUCH_INPUTS, Input) ~= nil
and UserInputService.TouchEnabled
and not OnComputer
and not OnConsole
if Controller.Computer ~= OnComputer then
Controller.Computer = OnComputer
end
Controller.ComputerChanged:Fire(OnComputer)
if Controller.Console ~= OnConsole then
Controller.Console = OnConsole
end
Controller.ConsoleChanged:Fire(OnConsole)
if Controller.Mobile ~= OnMobile then
Controller.Mobile = OnMobile
end
Controller.MobileChanged:Fire(OnMobile)
end
return Controller
Yeah, it’s a really hacky implementation. I wish there was a built-in API, but I guess this will suffice for now.
Changes in older release notes don’t get retroactively updated, it’s always been a thing.
c.c. @realYumiYumee @ramdoys @Velover3454 @AMisspelledUsernaem
You should avoid doing this. Read my post above:
Here’s the gist & some extra info too:
Design and implement your UI to update/function correctly based on the capabilities of the device, don’t try to classify what kind of device it is because that will lead to you making false assumptions about what the device is and how you should respond, you are inherently forcing yourself to ignore most of the actual device capabilities by trying to abstract it.
Best practices for UI design for device compatibility:
- Use offset units for size more, & calculate a scale factor based on the screen size to pass to a
UIScale
. This will result in a better experience on mobile because mobile devices use a virtual resolution that Roblox respects. This means that while a particular phone may be 4k, it might use a virtual resolution that is much lower to mimic a phone of the same size with a much lower resolution. - Anchor UIs to the sides/center of the screen with scale units &
AnchorPoint
orUILIstLayout
s and useUIPadding
to add margins. This will help with scaling if you implement it, because an element is always scaled around theAnchorPoint
. This will keep your UI looking consistent, things that should be on the left will be on the left, and things that should be on the right will be on the right.
Best practices for input design for device compatibility:
- Don’t conditionally listen to inputs based on device capabilities or what you think the device is because these events will only fire if the device has that capability anyway. In other words, always listen to the input events for the devices you are looking to support.
- Don’t build completely different UIs for completely different devices, and don’t make completely separate input implementations for different devices. Update the UI accordingly. This is what libraries like Fusion or React allow you to do with ease with their state management.
- In cases where you intend to drastically change the input scheme for ergonomics, change to the scheme based on the input method the user is actually using via
UserInputService:GetLastInputType()
. Don’t assume you know what the user’s device is based on its capabilities, because most of the capabilities onUserInputService
can be held by all devices. - Likewise, the same should be done when you’re trying to update imagery or indicators, you should do this based on the last input method used.
Generally, having UI state management like Fusion or React to make your UIs update dynamically, unify your codebase, and create re-usable UI will drastically improve your life when you’re working with UI because it allows you to do pretty much all of the above without a lot of hassle at all.
Oh i’m already using React, i didnt know that UserInputService.GetLastInputType existed .
Thanks for telling.
I mean really the best solution is proper device identification by Roblox. We still have to rely on assumptions about device features to guess on if a user is on mobile or a laptop or just has a very small screen. Like you said, assuming that having TouchEnabled means mobile just doesn’t represent what the large portion of devs are using it for.
There is genuine positive outcomes for having something that lets us know the kind of device a user is on so that we can properly adapt the game to fit their device. But, it doesn’t help that tech is constantly being innovated on, pushing the limits of what truly can be called a “tablet” versus a “laptop”. I still think a fairly robust system can help devs better determine when to add things like touch controls and UI scale.