Why my 3d model surface gui linked to camera is disappearing after some time

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?

2 Likes

well there are lots of posible reasons for your problem so we should point em out one by one in hopes of finding it :face_exhaling:

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:

game:GetService("StarterGui").ResetPlayerGuiOnSpawn = false

or recreate the model after respawn

  1. 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)

ya well i guess thats it, hope its fixed now :grinning_face_with_smiling_eyes:

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

now i switched to another app in the background, and then they suddenly disappeared

wait do you switch with shortcuts?? like Alt+Tab? or you js press another window open

both of them actually, i usually close programs at the background so they don’t waste pc resources


well now like this

wait it might be because of viewport size

whattt very weird! i never encounter this typa stuff when dealing with guis :eyes:

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

in past my scripts were spamming in f9 that models doesnt exist anymore


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 :sob:

it just destroys, doesnt exist in folder, which is in workspace

After refocusing from app it doesnt exist, like, engine destroys it or recreates camera

NEVERMIND, seems it fixed now because of

it was -500 by default thoooough..

oh damn glad you found it :laughing: :laughing: :laughing:

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.