Ideally, you would have multiple menu screen configurations for different aspect ratios.
For instance, once the screen gets narrow enough, you could move the title to be on top of the buttons, instead.
But it you really wanted to try and do it automatically I suppose you could.
You could use this function to compute the on-screen bounding box and see if its entirely within the screen:
-- returns true if a part's 2D bounding box on screen is fully within the screen rect's
local function OnScreen(camera, cframe, size)
-- 1. get all eight points in 3D space for the part
local pos, front, right, up = cframe.Position, cframe.LookVector, cframe.RightVector, cframe.UpVector
local hx, hy, hz = size.X / 2, size.Y / 2, size.Z / 2
local points = {
pos - front * hz - right * hx - up * hy,
pos - front * hz - right * hx + up * hy,
pos - front * hz + right * hx - up * hy,
pos - front * hz + right * hx + up * hy,
pos + front * hz - right * hx - up * hy,
pos + front * hz - right * hx + up * hy,
pos + front * hz + right * hx - up * hy,
pos + front * hz + right * hx + up * hy,
}
-- 2. compute AABB of the part's bounds on screen
local minX, maxX, minY, maxY = math.huge, -math.huge, math.huge, -math.huge
for i = 1, 8 do
local screenPoint = camera:WorldToViewportPoint(points[i])
local x, y = screenPoint.X, screenPoint.Y
if screenPoint.Z > 0 then
if x < minX then minX = x end
if x > maxX then maxX = x end
if y < minY then minY = y end
if y > maxY then maxY = y end
end
end
-- 3. AABB is within screen?
local w, h = camera.ViewportSize.X, camera.ViewportSize.Y
return minX >= 0 and maxX <= w and minY >= 0 and maxY <= h
end
Usage like:
if OnScreen(workspace.CurrentCamera, model:GetBoundingBox()) then
print("on screen completely")
else
print("off screen a bit")
end