I have been trying to create some UI for my game and it was going pretty well… until I fell into this problem.
I have a scrolling frame with a UIGridLayout
I have made it all to look fine at the current resolution,
but as soon as I resize the screen, the frame does this:
I can’t use scale due to the fact that the scrolling frame’s canvas size will be changing and it looks squished. Is there any way to keep it the same size but smaller (if that makes any sense)?
Try using Scale but with the UIAspectRatio object in the Frame
If that one doesn’t work… you might also want to listen to GetPropertyChangedSignal’Size’ and script it to set the Frames’ sizes to a specific size
There is not a built-in solution to this at this stage, so we’ll need to do some scripting to fix it. Firstly, though, you should do what PlantChampion said and use a UIAspectRatioConstraint (to make sure your frame is always square) and then listen for a signal. I will go more in-depth on this signal part.
You’ll need to essentially make your own Scale system. The Scale system of children of a ScrollingFrame effectively use ScrollingFrame.AbsoluteCanvasSize to calculate their size, unlike every other object wich uses Object.AbsoluteSize. So, all you really need to do is calculate with AbsoluteSize instead of AbsoluteCanvasSize. Calculating scale itself is pretty easy since you just do PARENT_SIZE * SCALE_SIZE. You’ll need to actually run this code, so here’s where the signal comes in. You’ll just need to listen to the signal for when the AbsoluteSize of the ScrollingFrame gets changed. Here’s some code demonstrating how this can be done:
-- This lets you configure what you want the size to be normally without having to change to script
local TargetScaleSize = Frame.Size
local function UpdateScale()
local ParentSize = ScrollingFrame.AbsoluteSize
-- Converting the scale size to pixels and then adding on any offsets
local X = (ParentSize.X * TargetScaleSize.X.Scale) + TargetScaleSize.X.Offset
local Y = (ParentSize.Y * TargetScaleSize.Y.Scale) + TargetScaleSize.Y.Offset
Frame.Size = UDim2.new(0, X, 0, Y)
end
ScrollingFrame:GetPropertyChangedSignal("AbsoluteSize"):Connect(UpdateScale)
UpdateScale()
Because what I am doing is creating a different number of frames every time this GUI enters the PlayerGui and then the sizes are controlled by a UIGridConstraint.
Problem is though, because the CellSize is {0,100,0,100}, this part
local X = (ParentSize.X * TargetScaleSize.X.Scale) + TargetScaleSize.X.Offset
local Y = (ParentSize.Y * TargetScaleSize.Y.Scale) + TargetScaleSize.Y.Offset
With a big logical headache, I have managed to get it to work with my setup. Thanks @PlantChampion@Partcline and @EmeraldSlash for your great responses
This is where you should be setting the TargetScaleSize in Scale. If your entire container frame scales with screen size, having its children (in this case, the grid items) scale would be a good idea too, and that’s where this solution really shines in my experience. You’ll just need to manually find the Scale values you want. Anyway, I’m aware you have fixed it so good job
I’d like to comment on this and say that this no longer requires any scripting. Here is my solution:
Add a UIGridLayout to the ScrollingFrame.
Add a UIAspectRatioConstraint to each member of the ScrollingFrame (which would be 1 since it’s a square).
For some reason, using this application mixture of UIGridLayout and UIAspectRatioConstraint makes each member move with an axis in the Y dimension. Make one Scale CellSize of the UIGridLayout to be the size of the square. Make the other Scale dimension to be small enough so that the member doesn’t move position.