TL:DR: The plugin adds a UDim attribute to UIStrokes which can be used in place of the Thickness property, allowing you to use scale in addition to offset.
UIStroke Scale Plugin:
Plugin Demo
Before:
After:
How it works
The plugin adds a simple UDim Attribute to every UIStroke
in the game, and automatically sets the Thickness
property accordingly.
How to use:
- Download and install the plugin.
- Set the
ThicknessUDim
attribute in the properties window or in ascript
like you would any UDim value.
Scale: The Scale part of the UDim
scales with the size of the frame (a Scale value of 1 will equal 1/10th of the average frame size)
Offset: The Offset part of the UDim
determines the offset in pixels irrespective of screen size. It functions identically to the default Thickness
property.
You can use both Scale and Offset values at the same time.
UIStroke Scale LocalScript:
The plugin can only scale UIStrokes while in Studio. In order to scale during a live game, the plugin will attempt to inject a LocalScript
into ReplicatedFirst
. This requires enabling Script Injection permission. Alternatively the code below can be copied into a LocalScript
and parented to ReplicatedFirst
. (the second method won’t allow for automatic updates should there be any)
[Note]: If the 'UIStrokeScale script is removed, scaling will occur only in Studio and cause unintended results in a live game
Other notes:
-
Avoid setting the
Thickness
property of UIStrokes as they will be completely overwritten byThicknessUDim
. To achieve the same behavior asThickness
, simply set the Offset part of theUDim
and leave the Scale set to 0. -
While in team create with multiple people who have the plugin enabled,
UIStrokes
onBillboardGuis
will appear to glitch out. Unfortunately this is unavoidable due to the nature of BillboardGui’s changing their AbsoluteSize relative to the Camera. Multiple people in a session means multiple cameras changing the same value. This is only an oddity in Studio and will not affect live games. -
The UIStrokeScale LocalScript can be used without the plugin. Certain features will not work like automatically creating
ThicknessUDim
Attributes and scaling UIStrokes while in edit mode. The latter makes it difficult to adjust UI elements, for this reason it is not recommended to use the LocalScript standalone.
UIStrokeScale LocalScript code
-- [UIStrokeScaled]
-- written by batteryday
-- LocalScript/game.ReplicatedFirst
local PLUGIN_NAME = script.Name
-- UiStroke --
local function onUIStrokeAdded(uiStroke)
local connections = {}
local function connect()
-- disconnect previous connection
for _,conn in pairs(connections) do
conn:Disconnect()
end
-- uiStroke must have a parent that is a GuiBase2d
if not uiStroke.Parent or not uiStroke.Parent:IsA("GuiBase2d") then return end
-- text objects
local isTextObject = false
if uiStroke.Parent:IsA("TextLabel") or uiStroke.Parent:IsA("TextButton") or uiStroke.Parent:IsA("TextBox") then
isTextObject = true
end
-- add ThicknessUDim Attribute if it doesn't already have
if not uiStroke:GetAttribute("ThicknessUDim") then
uiStroke:SetAttribute("ThicknessUDim",UDim.new(0,uiStroke.Thickness))
end
local function updateThickness()
local thicknessUDim = uiStroke:GetAttribute("ThicknessUDim")
local averageSize = (uiStroke.Parent.AbsoluteSize.X + uiStroke.Parent.AbsoluteSize.Y) / 2
-- use TextBounds for TextObjects
if isTextObject and uiStroke.ApplyStrokeMode == Enum.ApplyStrokeMode.Contextual then
averageSize = (uiStroke.Parent.TextBounds.X + uiStroke.Parent.TextBounds.Y) / 2
end
-- Scale of "1" will be 1/10 the average size of the frame
uiStroke.Thickness = thicknessUDim.Scale * averageSize / 10 + thicknessUDim.Offset
end
connections["thickness_udim_changed"] = uiStroke:GetAttributeChangedSignal("ThicknessUDim"):Connect(function()
if not uiStroke:GetAttribute("ThicknessUDim") or typeof(uiStroke:GetAttribute("ThicknessUDim")) ~= "UDim" then
uiStroke:SetAttribute("ThicknessUDim",UDim.new())
warn("["..PLUGIN_NAME.."]: don't change 'ThicknessUDim to a non-UDim value while using '"..PLUGIN_NAME.."' plugin")
end
updateThickness()
end)
connections["absolute_size_changed"] = uiStroke.Parent:GetPropertyChangedSignal("AbsoluteSize"):Connect(updateThickness)
if isTextObject then
connections["text_bounds_changed"] = uiStroke.Parent:GetPropertyChangedSignal("TextBounds"):Connect(function()
updateThickness()
end)
end
updateThickness()
end
-- reconnect when parent changes
uiStroke.AncestryChanged:Connect(function()
connect()
end)
connect()
end
-- tag all UIStrokes in game
for _,uiStroke in ipairs(game:GetDescendants()) do
if uiStroke:IsA("UIStroke") then
onUIStrokeAdded(uiStroke)
end
end
game.DescendantAdded:Connect(function(uiStroke)
if uiStroke:IsA("UIStroke") then
onUIStrokeAdded(uiStroke)
end
end)
I hope you found this useful!