return function(camera: Camera, uiModel: Model)
local RunService = game:GetService("RunService")
local primary = uiModel.PrimaryPart or uiModel:FindFirstChild("PrimaryPart")
if not primary then return end
local function projectedFraction(d)
if camera.ViewportSize.X <= 1 then
return 0
end
local _, size = uiModel:GetBoundingBox()
local corners = {}
for _, sx in ipairs({-1, 1}) do
for _, sy in ipairs({-1, 1}) do
for _, sz in ipairs({-1, 1}) do
local localPos = Vector3.new(size.X/2 * sx, size.Y/2 * sy, size.Z/2 * sz)
local worldPos = (camera.CFrame * CFrame.new(0, 0, -d)):PointToWorldSpace(localPos)
local vp = camera:WorldToViewportPoint(worldPos)
table.insert(corners, vp.X)
end
end
end
local minX, maxX = math.huge, -math.huge
for _, x in ipairs(corners) do
if x < minX then minX = x end
if x > maxX then maxX = x end
end
return (maxX - minX) / camera.ViewportSize.X
end
local function computeBestD(desiredFraction)
local minD, maxD = 1, 14
for _ = 1, 8 do
local mid = (minD + maxD) / 2
if projectedFraction(mid) > desiredFraction then
minD = mid
else
maxD = mid
end
end
return (minD + maxD) / 2
end
local function getDesiredScreenFraction()
local aspectRatio = camera.ViewportSize.X / camera.ViewportSize.Y
local frac = 0.12 + (aspectRatio - 1.3) * 0.03
return math.clamp(frac, 0.11, 0.2)
end
local desiredScreenFraction = getDesiredScreenFraction()
local bestD = computeBestD(desiredScreenFraction)
local lastSize = camera.ViewportSize
local heightFraction = 0.2
local sideFraction = 0.725
local tiltX, tiltY, tiltZ = math.rad(5), math.rad(-3), math.rad(3)
local faceForward = CFrame.Angles(0, math.rad(130), 0)
local currentPos = Vector3.zero
local currentRot = CFrame.identity
RunService.PreRender:Connect(function()
bestD = math.clamp(bestD, 2, 12)
if camera.ViewportSize.X <= 1 or camera.ViewportSize.Y <= 1 then return end
if camera.ViewportSize ~= lastSize then
desiredScreenFraction = getDesiredScreenFraction()
bestD = computeBestD(desiredScreenFraction)
lastSize = camera.ViewportSize
end
local hfov = 2 * math.atan(math.tan(math.rad(camera.FieldOfView) / 2) * (camera.ViewportSize.X / camera.ViewportSize.Y))
local offsetX = math.tan(hfov / 2) * sideFraction * bestD
local offsetY = heightFraction * bestD
local offsetZ = -bestD
local offset = CFrame.new(offsetX, offsetY, offsetZ) * CFrame.Angles(tiltX, tiltY, tiltZ)
local targetCF = camera.CFrame * offset * faceForward
local targetPos = targetCF.Position
local targetRot = targetCF - targetCF.Position
currentPos = currentPos:Lerp(targetPos, 0.9)
currentRot = currentRot:Lerp(targetRot, 0.7)
uiModel:PivotTo(currentRot + currentPos)
end)
end
here’s my code so, when I minimize the screen to another application, or after a couple of minutes i change focus from the client, the gui simply disappears, the parent is nil, its just destroys
what’s the problem?
well there are lots of posible reasons for your problem so we should point em out one by one in hopes of finding it
1, if the surfacegui (or the model containing it) is inside playergui, roblox can reset the guiwhen the character respawns or when “ResetPlayerGuiOnSpawn” is enabled. so you should add this:
dont place uiModel.Parent in workspace.CurrentCamera, place it straight up in wrokspace instead
uiModel.Parent = workspace
also little tip: its better to store connections so garbage aint piling up. change this
RunService.PreRender:Connect(function()
to something like this
local connection
connection = RunService.PreRender:Connect(function()
if not uiModel or not uiModel.Parent then
connection:Disconnect()
return
end
--your code starts here
end)
well, it’s still disappears however, in the summer of 2025 when I made this code, everything worked fine and did not disappear, so I don’t know, I think this is really an engine bug
whattt very weird! i never encounter this typa stuff when dealing with guis
you should try debugging it first like printing if it exists
local RunService = game:GetService("RunService")
local StarterGui = game:GetService("StarterGui")
local gui = StarterGui:FindFirstChild(guiName)
local guiName = "thatguithingy"
local timer = 0
if gui then
gui.Destroying:Connect(function()
print("gui destroyed by smthin")
end)
gui.AncestryChanged:Connect(function(_, newparent)
if not parent then
print("gui's parents changed to ", newparent:GetFullName())
end
end)
end
RunService.Heartbeat:Connect(function(dt)
timer += dt
if timer >= 1 then
timer = 0
if gui then
print("still here!")
end
end
end)
well ok i’ll try, just my surface gui is on part, which is in model, this model is linked to camera, to imitiate perspective effect, all of them in folder in workspace
i disabled surface gui but during debugging its just disappears like i think it because of occulusion culling or smth, it disappears even if streaming enabled is false
doesnt exist anymore or doesnt exist at all?? maybe you wrote the instance directory incorreclty? how come the gui doesnt exist this is very confusing me