Code for detecting distance from SurfaceGui/BillboardGui doesn't work

If you look at a SurfaceGui from an angle, you can view it at much higher distances than looking straight at it. I am wondering how I would detect if a SurfaceGui is visible, my current code just gets the distance from the center of the face to the camera.

Surface:

-- Gets face
local Face = SurfaceGui.Face
if not Face then return 0 end
-- Gets center of face
local FaceCFrame = Adornee.CFrame * CFrame.new((Adornee.Size/2)*KiwiUtility.FaceList[Face.Name])
-- Gets distance to camera
return (Camera.CFrame.Position - FaceCFrame.Position).Magnitude

Billboard:

-- Distance checks
local Distance = (Camera.CFrame.Position - WorldPosition).Magnitude
if IgnoreCovering == nil and BillboardGui.MaxDistance > 0 then
	if Distance > BillboardGui.MaxDistance then return false, Vector2.new(), Distance end
end

This same issue also happens with billboards, I can’t make bug reports so I am just asking for a workaround.

1 Like

1 Like

SurfaceGui (this just returns the distance from the closest point on the respective surfaceGui.Face), compare this directly with surfaceGui.MaxDistance to return whether or not it’s currently visible, point would be Camera.CFrame.Position:

local function calculateDistanceFromClosestPointOnFace(point, part)
	local surfaceGUi = part:WaitForChild('SurfaceGui')
	
	local face = surfaceGui.Face
	local faceVec = Vector3.fromNormalId(face)
	
	local pointOnFace = faceVec * 0.5 * part.Size
	
	local pointOnPart = part.CFrame * CFrame.new(pointOnFace)
	local cameraLocal = pointOnPart:PointToObjectSpace(camera.CFrame.Position)
	local clampedToFace = cameraLocal:Max(-0.5 * part.Size):Min(0.5 * part.Size) * (Vector3.one - faceVec:Abs()) + pointOnFace
	
	return (point - pointOnPart:PointToWorldSpace(clampedToFace)).Magnitude
end

As for Billboard, are you using any of the offsets? That will complicate things a bit, let me know.

1 Like

Longer parts can still trigger the GUI from distance using this function (the custom hover cursor is active), I need a solution that would work reliably for any SurfaceGui

And for offsets on BillboardGuis, I am using SizeOffset, StudsOffset, and StudsOffsetWorldSpace, not using extents offset. Heres my current calculations for Billboards:

    -- Values
	local Size = BillboardGui.AbsoluteSize
	local SizeOffset = BillboardGui.SizeOffset
	local StudsOffset = BillboardGui.StudsOffset
	local StudsOffsetWorldSpace = Adornee.CFrame:ToWorldSpace(CFrame.new(BillboardGui.StudsOffsetWorldSpace))

	-- WorldPosition
	local WorldPosition = StudsOffsetWorldSpace.Position + StudsOffset	
	workspace.PartTest.Position = WorldPosition
	
	-- Screen Position
	local ScreenPosition = Camera:WorldToScreenPoint(WorldPosition)
	
	-- Distance checks
	local Distance = (Camera.CFrame.Position - WorldPosition).Magnitude
	if IgnoreCovering == nil and BillboardGui.MaxDistance > 0 then
		if Distance > BillboardGui.MaxDistance then return false, Vector2.new(), Distance end
	end

I tried it on a square part, my bad. It looks like the camera’s point on the face needs to be constrained to be within the smallest of the two axes adjacent to faceVec, so this should work for determining visibility:

local function calculateDistanceFromClosestPointOnFace(point, part)
	local surfaceGui = part:WaitForChild('SurfaceGui')

	local face = surfaceGui.Face
	local faceVec = Vector3.fromNormalId(face)

	local pointOnFace = faceVec * 0.5 * part.Size

	local pointOnPart = part.CFrame * CFrame.new(pointOnFace)
	local cameraLocal = pointOnPart:PointToObjectSpace(point)
	
	local smallestAxis
	
	if faceVec.X >= 0.001 then
		smallestAxis = math.min(part.Size.Y, part.Size.Z)
	elseif faceVec.Y >= 0.001 then
		smallestAxis = math.min(part.Size.X, part.Size.Z)
	else
		smallestAxis = math.min(part.Size.X, part.Size.Y)
	end
	
	local smallest = Vector3.one * smallestAxis
	
	local clampedToFace = cameraLocal:Max(-0.5 * smallest):Min(0.5 * smallest) * (Vector3.one - faceVec:Abs()) + pointOnFace
	
	return (point - pointOnPart:PointToWorldSpace(clampedToFace)).Magnitude
end

I will get back to you on the BillboardGui

I decided I will make my own max distance instead of using Roblox’s “interesting” system, your function works a bit better than the one before, but I think its better to use a system that hides at the distance you set it at

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