How can I make a BillboardGUI behave like a ScreenGUI?

I would like to make a BillboardGUI have the static properties of a ScreenGUI, as in I want the BillboardGUI to stay on screen without any change in size and position no matter where I am on the game world. The reason I want to do this instead of just using ScreenGUIs is to give the GUI the ability to render behind models that are intended to be positioned sufficiently close to the camera (such as players in a 2D perspective), as I could not find a way to do so with ScreenGUIs.

This BillboardGUI is located inside the StarterGui. My idea for getting this to work was to simply change the Adornee of the GUI to the Workspace Camera in the editor, with the assumption that doing this will make the GUI always stick to the current position of the camera, at which point I could simply do an Offset to make sure it’s visible, and models in between that Offset will be rendered over of it.
However, doing this does not work, as the BillboardGUI has no Adornee when I run the game. Even if I don’t run the game, setting the Camera as the Adornee still keeps the GUI stuck in the same place as before (that being the center of the Baseplate).

Next, I attempted to create a Local Script inside the GUI which changes the Adornee/Parent of the BillboardGUI after waiting for the Workspace’s Camera to load. I looked through existing code in forums where people wanted to make overhead UI for players, and attempted to retrofit that into my use case.

script.Parent.Parent = workspace:WaitForChild("CurrentCamera")
script.Parent.Adornee = workspace:WaitForChild("CurrentCamera")

This does not work either. Neither the Parent nor the Adornee successfully gets updated with the current code I have.

I do not know if this is even possible, or if it is, whether or not it will require more complex code than just changing Parents and Adornees. While I would hope for a fairly simple way to get this to work, any solution that works would be appreciated as a learning experience.
As an additional note, I did not wish to use Viewport Frames for the players, as I wanted the players to have full lighting support and such.

8 Likes

Like this?

I am a little confused on what you want. If you want the above effect, you change the size of BillBoardGui and all Gui instances into using Scale instead of offset to size them.

4 Likes

Not quite. That’s the kind of purpose I believe BillboardGUIs are used for normally.

What I know about BillboardGUIs is that they are essentially 2D UIs that exist within the game world without being displayed on an existing surface, like SurfaceGUIs. As such, you can be in front/behind them, while ScreenGUIs are rendered on top of the game world.

What I want is for the BillboardGUI to always look like how this ScreenGUI looks, even if my camera moves around:


(Top of the screen, timer in the center)
The only thing that makes this functionally different to the ScreenGUI is that when you are close enough to objects, they can be rendered over the GUI because of how this type of GUI works.

3 Likes

can’t you use SurfaceGui on a Part and have it positioned front of the camera instead?

2 Likes

If I were to do that, I would have minor distortion effects depending on the camera FOV, as the GUI would now be a (technically) 3D entity. This would also make it complicated to ensure that the scale and of the Part completely fills the entire screen at any given distance. With the variable aspect ratios you can get with players using different kinds of devices, that can cause further complications in terms of the scaling of the Part, as well as increasing FOV distortion on wider displays.

2 Likes

ok, so i figured something out:

local player = game.Players.LocalPlayer
local camera = workspace.CurrentCamera
local part = game.Workspace:WaitForChild("surfacegui") -- replace with part with the billboardgui on it

-- position the part in front of the player's camera
local function setPosition()
	local Size = UDim2.new(0, camera.ViewportSize.X, 0, camera.ViewportSize.Y)
	part.BillboardGui.Size = Size
	
	local offsetVector = Vector3.new(0, 0, -5)
	part.Position = camera.CFrame:PointToWorldSpace(offsetVector)
	part.CFrame = CFrame.new(part.Position, camera.CFrame.Position)
end

game:GetService("RunService").RenderStepped:Connect(function()
	setPosition()
end)

4 Likes

I’m having trouble implementing this code properly. May I see the part’s Explorer location and its structure?

2 Likes

basically i made the ui in screengui and pasted the frame to the billboardgui:
image
to:
image

also pardon for “surfacegui” i meant to type billboardgui (in the script)

1 Like

Where does the LocalScript go?

1 Like

i’ve placed it in StarterGui

…

1 Like

I’ve tried putting it inside the part’s BillboardGUI, and also inside the StarterGUI without another parent, but I’m still having trouble, May I see the structure with the part and script in view?

1 Like

alright, forgive me since im bad at explaining lol but here i organized the script, maybe it will be easier to understand it:

image

the BillboardGui.Adornee is set to the BillboardPart, the part can be anything, the properties of the part doesn’t matter, just make sure it’s transparent.

and the frame and content of the gui are sized in scale, not offset.

the script:

local player = game.Players.LocalPlayer
local camera = workspace.CurrentCamera
local part = script.BillboardPart

local function setPosition()
	local Size = UDim2.new(0, camera.ViewportSize.X, 0, camera.ViewportSize.Y)
	script.BillboardGui.Size = Size
	
	local offsetVector = Vector3.new(0, 0, -5)
	part.Position = camera.CFrame:PointToWorldSpace(offsetVector)
	part.CFrame = CFrame.new(part.Position, camera.CFrame.Position)
end

game:GetService("RunService").RenderStepped:Connect(function()
	setPosition()
end)
2 Likes


Is there an error here?

1 Like

nope, you inserted a breakpoint, maybe by accident.
you can delete it by right-clicking on it:
image

2 Likes

Wonderful, it works perfectly! Thank you very much for taking this much time to help me.

1 Like

no problem, happy to help :slight_smile:

2 Likes

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