EDIT: Roblox has expanded their UI tools a lot as of lately and it pretty much makes this method obsolete although this still does work.
I’ve been working on a new game recently, so I’ve been experimenting with rescaling UIs properly. My first solution worked, but wasn’t as efficient as it could be and required me to keep track of every UI element there is. It was a hassle, so I rethought my solution, and came up with a more mathematical way of doing it. Here is my solution.
This method allows you to make your UIs in studio using offset if you want to, as long as you know the resolution you’re making it with. (Can be seen via ScreenGui’s AbsoluteSize property)
First we define our resolution. (The native resolution you are developing your UI on) You also need to decide if you want the UI to scale based on the X or Y axis. (I usually prefer X axis)
local GUI = script.Parent --ScreenGui
local Updatelog = GUI.UpdateLog
local Resolution = Vector2.new(1397,682)
Now, we will be using this formula from the wiki to calculate the original absolute size and position of the element.
local OrigAbsSize = Vector2.new(Updatelog.Size.X.Offset + Resolution.X * Updatelog.Size.X.Scale,Updatelog.Size.Y.Offset + Resolution.Y * Updatelog.Size.Y.Scale)
local OrigAbsPos = Vector2.new(Updatelog.Parent.AbsolutePosition.X + Updatelog.Position.X.Offset + Updatelog.Parent.AbsoluteSize.X * Updatelog.Position.X.Scale,Updatelog.Parent.AbsolutePosition.Y+Updatelog.Position.Y.Offset + Updatelog.Parent.AbsoluteSize.Y * Updatelog.Position.Y.Scale)
Now we setup a ScreenGui.Changed event to detect if the player changes the resolution of the game. Inside of this event, we will make a ratio of the current GUI AbsoluteSize.X with our original X axis size. After this, we will use the ratio and calculate how many pixels to offset the GUI by.
GUI.Changed:connect(function(Prop)
if Prop == "AbsoluteSize" then
local Ratio = GUI.AbsoluteSize.X/Resolution.X
local CalcSize = Vector2.new(OrigAbsSize.X-(OrigAbsSize.X*Ratio),OrigAbsSize.Y-(OrigAbsSize.Y*Ratio))
local CalcPos = Vector2.new(OrigAbsPos.X-(OrigAbsPos.X*Ratio),OrigAbsPos.Y-(OrigAbsPos.Y*Ratio))
end
end)
Finally for the offset values of the element, we just do the original values - Calculated values
Updatelog.Size = UDim2.new(Updatelog.Size.X.Scale,OrigAbsSize.X-CalcSize.X,Updatelog.Size.Y.Scale,OrigAbsSize.Y-CalcSize.Y)
Updatelog.Position = UDim2.new(Updatelog.Position.X.Scale,OrigAbsPos.X-CalcPos.X,Updatelog.Position.Y.Scale,OrigAbsPos.Y-CalcPos.Y)
Final Code:
local GUI = script.Parent --ScreenGui
local Updatelog = GUI.UpdateLog
local Resolution = Vector2.new(1397,682)
local OrigAbsSize = Vector2.new(Updatelog.Size.X.Offset + Resolution.X * Updatelog.Size.X.Scale,Updatelog.Size.Y.Offset + Resolution.Y * Updatelog.Size.Y.Scale)
local OrigAbsPos = Vector2.new(Updatelog.Parent.AbsolutePosition.X + Updatelog.Position.X.Offset + Updatelog.Parent.AbsoluteSize.X * Updatelog.Position.X.Scale,Updatelog.Parent.AbsolutePosition.Y+Updatelog.Position.Y.Offset + Updatelog.Parent.AbsoluteSize.Y * Updatelog.Position.Y.Scale)
GUI.Changed:connect(function(Prop)
if Prop == "AbsoluteSize" then
local Ratio = GUI.AbsoluteSize.X/Resolution.X
local CalcSize = Vector2.new(OrigAbsSize.X-(OrigAbsSize.X*Ratio),OrigAbsSize.Y-(OrigAbsSize.Y*Ratio))
local CalcPos = Vector2.new(OrigAbsPos.X-(OrigAbsPos.X*Ratio),OrigAbsPos.Y-(OrigAbsPos.Y*Ratio))
Updatelog.Size = UDim2.new(Updatelog.Size.X.Scale,OrigAbsSize.X-CalcSize.X,Updatelog.Size.Y.Scale,OrigAbsSize.Y-CalcSize.Y)
Updatelog.Position = UDim2.new(Updatelog.Position.X.Scale,OrigAbsPos.X-CalcPos.X,Updatelog.Position.Y.Scale,OrigAbsPos.Y-CalcPos.Y)
end
end)
Video of it working:(Only Updatelog in the video I setup to scale, Also scales down to Mobile fine)
https://dl.dropboxusercontent.com/u/53742709/ShareX/2016/05/2016-05-24_17-35-05.mp4
I know I didn’t explain the math very much, but you should be able to deduce what I’m doing. I’m working on a module using this method, but I figured I’d release my method so you can do it yourself before I do. (You also might want to turn it into a function so you can call it when the game starts up as the changed event won’t fire when a player joins if they have a different screen res)