If keeping your UI pixel-perfect to the design matters at all, you’ll likely need to use UIScale to avoid having to mess with an unholy amount of UIAspectRatioConstraints. Often, unless you specifically need to deal with text lengths, using relative sizing (UDim2 Scale) with a couple of aspect ratio constraints is ok.
If you wish to use UIScale, here’s a Roact component I wrote recently that scales UI fairly well:
local Workspace = game:GetService("Workspace")
local GuiService = game:GetService("GuiService")
local Camera = Workspace.CurrentCamera
local TopInset, BottomInset = GuiService:GetGuiInset()
local Roact = require("Roact")
local Scale = Roact.PureComponent:extend("Scale")
function Scale:init()
self:update()
self.Listener = Camera:GetPropertyChangedSignal("ViewportSize"):Connect(function()
self:update()
end)
end
function Scale:update()
local currentSize = self.props.Size
local viewportSize = Camera.ViewportSize - (TopInset + BottomInset)
self:setState({
Scale = 1 / math.max(
currentSize.X / viewportSize.X,
currentSize.Y / viewportSize.Y
)
})
end
function Scale:willUnmount()
self.Listener:Disconnect()
end
function Scale:render()
return Roact.createElement("UIScale", {
Scale = self.state.Scale * self.props.Scale
})
end
Scale.defaultProps = {
Scale = 1
}
return Scale
The component tries to make element as big as possible while still fitting in the screen, then multiplies that by Scale
. Here’s an example of the usage:
Roact.createElement(Scale, {
Size = Vector2.new(150, 150),
Scale = 0.2
})
The result is an element that will always fit within the boundaries of the screen, no matter what resolution.