Introducing Accessibility Settings

What’s up, Developers!

We are excited to announce several new settings for the Roblox app - you can now enable Reduced Motion, set your preferred Background Transparency, and enable or disable the shortcut for Keyboard Navigation. These have been added to both the in-experience menu settings, as well as app settings.

Overview of Changes

There are two new properties available for developers that provide you with the user’s preference for motion and transparency, as well as events for when they change.

chatwindow

okloadingscreenbutactually

Note: PreferredTransparency is referred to as Background Transparency in the app, for a better user experience, but the API returns the inverse value for compatibility with how the engine represents transparency. Similarly, ReducedMotion is referred to as Reduce Motion in the app for more consistency with other settings.

How to Use

Usage of these settings should be fairly straightforward. The values are read directly from GuiService and their changed events are retrieved by using GetPropertyChangedSignal.

Reduced Motion

We followed some common patterns in handling reduced motion and would like to share them with you for inspiration!

When reduced motion is enabled…

  • When a UI element is flying in from far off screen, fade it in instead, or if that is not feasible have an instant transition. CanvasGroups are very helpful for fading in complex UI elements altogether.
  • When an element has a consistently looping animation that involves motion, stop the animation altogether or replace it with something in-place.

The following code snippet shows a consistently animated “rain” effect made with UI elements, pausing the animation when reduced motion is enabled.

lightsrain

Click here to view the code!
local GuiService = game:GetService("GuiService")
local TweenService = game:GetService("TweenService")
local Players = game:GetService("Players")
local PlayerGui = Players.LocalPlayer:WaitForChild("PlayerGui", 3)

local screenGui = Instance.new("ScreenGui")
screenGui.IgnoreGuiInset = true
screenGui.Parent = PlayerGui

local container = Instance.new("Frame")
container.Size = UDim2.fromScale(1, 1)
container.BackgroundTransparency = 1
container.Parent = screenGui

local tweens = {}

-- Create 100 frames of random colors and random positions
local FRAME_SIZE = 20
for i = 1, 100 do
	local frame = Instance.new("Frame")
	frame.Size = UDim2.new(0, FRAME_SIZE, 0, FRAME_SIZE)
	frame.Position = UDim2.fromScale(math.random(), math.random())
	frame.BackgroundColor3 = Color3.new(math.random(), math.random(), math.random())
	frame.BorderSizePixel = 0
	frame.Parent = container
	
	local tweenInfoStart = TweenInfo.new(1 - frame.Position.Y.Scale, Enum.EasingStyle.Linear)
	local tweenStart = TweenService:Create(frame, tweenInfoStart, { Position = UDim2.fromScale(frame.Position.X.Scale, 1) })
	
	local tweenInfoEnd = TweenInfo.new(frame.Position.Y.Scale, Enum.EasingStyle.Linear)
	local tweenEnd = TweenService:Create(frame, tweenInfoEnd, { Position = frame.Position })

	tweens[tweenStart] = true
	local startTweenLocation = UDim2.fromScale(frame.Position.X.Scale, 0) 
	tweenStart.Completed:Connect(function ()
		tweens[tweenStart] = true
		frame.Position = startTweenLocation
		tweenEnd:Play()
		tweens[tweenEnd] = true
	end)

	tweens[tweenEnd] = false
	tweenEnd.Completed:Connect(function ()
		tweens[tweenEnd] = false
		tweenStart:Play()
		tweens[tweenStart] = true
	end)
end


function onReducedMotionUpdate()
	for tween, isActive in pairs(tweens) do
		if isActive then
			if GuiService.ReducedMotionEnabled then
				tween:Pause()
			else
				tween:Play()
			end
		end
	end
end

local reducedMotionSignal = GuiService:GetPropertyChangedSignal("ReducedMotionEnabled")
reducedMotionSignal:Connect(onReducedMotionUpdate)
onReducedMotionUpdate()

Here is an example of a menu option fading in screen instead of flying in from the top.

menuanimate

Click here to view the code!
local GuiService = game:GetService("GuiService")
local TweenService = game:GetService("TweenService")

local screenGui = script:FindFirstAncestorOfClass("ScreenGui")
-- CanvasGroup only supports Sibling ZIndexBehavior
screenGui.ZIndexBehavior = Enum.ZIndexBehavior.Sibling

-- This script expects to be parented to a button that controls the menu,
-- a sibling of the button.
local button = script.Parent
local canvasGroup = button.Parent.Menu

local canvasGroupOpenPosition = canvasGroup.Position
local canvasGroupClosedPosition = canvasGroupOpenPosition - UDim2.fromScale(0, 2)

local menuIsOpen = false
canvasGroup.Position = canvasGroupClosedPosition

-- Tweens to slide the canvasGroup into and out of the screen
local slideInTween = TweenService:Create(canvasGroup, TweenInfo.new(0.35), { Position = canvasGroupOpenPosition })
local slideOutTween = TweenService:Create(canvasGroup, TweenInfo.new(0.35), { Position = canvasGroupClosedPosition })

-- Tweens to fade the canvasGroup in and out
local fadeInTween = TweenService:Create(canvasGroup, TweenInfo.new(0.2), { GroupTransparency = 0 })
local fadeOutTween = TweenService:Create(canvasGroup, TweenInfo.new(0.2), { GroupTransparency = 1 })
fadeOutTween.Completed:Connect(function()
	canvasGroup.Position = canvasGroupClosedPosition
	canvasGroup.GroupTransparency = 0
end)

button.Activated:Connect(function()
	local reducedMotionEnabled = GuiService.ReducedMotionEnabled
	if menuIsOpen then
		if reducedMotionEnabled then			
			fadeOutTween:Play()
		else
			slideOutTween:Play()
		end
	else
		if reducedMotionEnabled then
			canvasGroup.GroupTransparency = 1
			canvasGroup.Position = canvasGroupOpenPosition

			fadeInTween:Play()
		else
			slideInTween:Play()
		end
	end
	menuIsOpen = not menuIsOpen
end)


Preferred Transparency

We chose to provide the users transparency preference in a way that could be used very easily by developers. If you have a UI element with a semi- or fully-transparent background that you think should respect the value of a user’s transparency preference, simply multiply your default background transparency by the user’s preference. As the value approaches 0 it will become more opaque, becoming fully opaque at 0. Make sure to hook this up to the signal so it updates in real time!

preferredtransparencylights

Click here to view the code!
-- Parent this to any TextLabel
local GuiService = game:GetService("GuiService")
local TextLabel = script.Parent

-- Set the TextLabel's background transparency by combining the default background transparency and the player's preferred transparency
local DEFAULT_TRANSPARENCY = TextLabel.BackgroundTransparency

local function setBackgroundTransparency()
	print(GuiService.PreferredTransparency)
	TextLabel.BackgroundTransparency = GuiService.PreferredTransparency * DEFAULT_TRANSPARENCY
end

GuiService:GetPropertyChangedSignal("PreferredTransparency"):Connect(setBackgroundTransparency)
setBackgroundTransparency()


Next Steps

This feature is enabled for all users and is ready to use in development now :tada: Please leave any requests and feedback in the comments below. If you end up implementing support for these features, consider sharing with us! What other accessibility settings would you like to see in the future?

With that, and a big thank you to @coolpenguino1 for his hard work on this project this summer, we are looking forward to being more accessible with you all :smiling_face_with_three_hearts:

241 Likes

This topic was automatically opened after 10 minutes.

It almost feels alien to see that Roblox has finally realised that perhaps the user knows what is best for their own experience.

Very welcoming additions.

Now we just need the same but for graphical options…

113 Likes

This is a pretty cool update, i will 100% turn up the transparency to as high as it can go lol

14 Likes

Very nice, always good to see accessibility settings!

One suggestion would be to allow developers to add to the official settings menu. Currently, our experience has its own accessibility menu and I would love to reduce the friction for our users by consolidating these interfaces into 1 (the one being the official settings menu!). Can split up the settings menu to be like, “Roblox-Wide settings” and “Experience-Level settings”.

Here are some examples of our accessibility settings, which can be some ideas for accessibility that can be added to the menu:

General accessibility is always good to see, but every experience is different so giving more control to creators who know what their experience should look like will always be a plus. I know Roblox is pretty icky about letting their users edit their core UI, so I do think the above suggestion would be a pretty good middle ground for Roblox to consider. It gives a space for creators while keeping true to their vision.

64 Likes

I’m surprised/disappointed about the lack of color blindness options considering that should be the single most common disability, though this is a very good addition to the game and I hope more options will be added in the near future.

23 Likes

Now this? THIS is an amazing update to see! Having the option to view a player’s accessibility settings is a huge milestone for Roblox, and I’m excited to see this expanded in the future! Subtitles, colorblind modes, disabling stylized fonts, and plenty more could easily fit here and help streamline accessibility for both developers and players! Thank you!!

16 Likes

I know the keyboard navigation one was a pain point for a lot of players, myself included, so I’m especially happy to see that one, especially after having waited so long for it to be an option (and seeing it enabled then disabled in the past :sad:).

I’m also glad Roblox is starting to beginning to create accessibility features, and that they’re being implemented into the main application. Hopefully these new accessibility options will bring awareness to developers with respect to how important accessibility options are for games. I know many games don’t include accessibility options when they definitely should.

8 Likes

This is super neat stuff!
Though I do notice a few options that might be missing.

So there’s a “reduced motion” option now, but will there also be a “reduced flashing” option?

Bright flashing lights and epilepsy inducing effects do not always include or count as motion.
Sometimes it’s simply a still / unmoving thing that just flashbangs your face with super bright, flashy colors.

Maybe someone doesn’t want reduced motion but would like to have reduced flashing.

Other accessibility settings I would also like to see is perhaps emulating mouse buttons or keyboard buttons that not everyone has.

The ability to rebind keys and buttons would be an absolute game changer but perhaps I’m asking too much.

7 Likes

Highly recommend people who want this to read through the following:

In a perfect world, developers would be allowed to have their own menu that house things, be able to use the Escape key, and maybe get rid of the Roblox logo at the top-left of the screen in some way. But, we are not in a perfect world, so I doubt this functionality of one menu, in the way I’d like, will ever happen.

8 Likes

This is great!

Would be cool to expand this to more general preferences as well such as allowing a user to set their preferred theme (dark/light) etc. and allow games to use this data to personalize the experience.

10 Likes

Still waiting for developers to be able to access what the players graphics quality/estimated device power is even if they have automatic turned on, especially if Roblox is going down the route of allowing settings to transfer between games and developers to be able to change things based on these settings

4 Likes

This is a welcoming change to see, I’ll try and implement this API into all my upcoming experiences! One concern I do have is the placement of these settings, it appears as if the “Settings” menu is getting filled up with too many settings to the point that scrolling down to these new settings is a nuance and clicking the wrong setting is becoming all to common for me.

One thing I will also bring up is a UX-issue that this new API has brought up in my experience. I used to always provide players with a “Reduced Motion” option in my in-experience settings menu however now because of this new API I have a major decision to make. Removing the option is not ideal because players who are unaware of the built-in setting will lose the accessibility setting without any-notice, however keeping it creates a bit of nuance too: If a player has one of the settings on (in-experience or Roblox) yet the other one off; which one do I respect, could it be confusing to players to show a different value in my in-experience settings to the Roblox menu or vice-versa? I guess this is more of a problem for me to deal with now, as I have to weight the impact of a confusing menu vs disabling the option that many players may have intentionally selected to enable.


It also appears as if the old CoreGui (which is still available to some users, especially in Studio) does not respect these settings:

7 Likes

At first, I thought you could change the Transparency of the whole UI, but it can just be changed to be opaque. (The value can be used in the opposite way I know, but that will be confusing for players)

What I mean is that some players want to make some stuff transparent instead of opaque to have a clear view.


In my game stuff are Opaque by default, and I have a setting to make it all transparent.

6 Likes

Can we get advanced graphics settings please, we have been asking for 10 years, please.

11 Likes

Hope you’re aware of this. Seems to be directly tied to this update.

6 Likes

This extends further than just “consoles”, any user with the old CoreGui will have the CoreGui mess up like this upon changing the accessibility setting.

5 Likes

It would be great if we had a debugging tool for accessibility, for example, being able to simulate different color blindness’s to see how our game would look like to someone with variety of vision problems. Chrome Dev Tools have it:

Code_B2ft6sOaDD

20 Likes

Thinking for yourself? Knowing what’s best for you yourself? Dude, that’s so 2019.

9 Likes

still waiting for a setting to customize touch screen sensitivity…

we’re currently still stuck with scripting it in ourselves

5 Likes