3D GUI won't stay onscreen


I am trying to replace 2D UIs with 3D UIs, how I currently set it up is I set the Adornee of the SurfaceGui to a Part that is parented to the Camera and changes the CFrame to stay with the Camera with added offsets and spring offsets etc etc. I have looked at a few resources explaining how to make 3D UIs behaving like 2D but they are complicated and don’t solve what specific issue I’m having


Everything has been going well but I have been having issues with keeping them on the screen like how ScreenGuis do. EXAMPLE BELOW

I know the solution needs some math and I am not really good at math so any help would be greatly appreciated.

This is my module’s update code:

-- GUIObject is the Part the SurfaceGui is Adorned to
-- You do not need to worry about the SpringOffsets
self.Offsets is a table and it looks like this: {
   Position = Vector3.new(x,x,x),
   Rotation = Vector3.new(x,x,x), -- Don't worry about this.
   Size = Vector3.new(x,x,x) -- Don't worry about this.
function GUI3D:Update(dt)
	local GUIObject = self.GUIObject
	local Offsets = self.Offsets
	local SpringOffsets = {
		Position = Vector3.zero,
		Rotation = Vector3.zero,
		Size = Vector3.zero
	for i,v in self.SpringOffsets do
		if SpringOffsets[i] then
			SpringOffsets[i] = v.Position
	local ScreenSize = Camera.ViewportSize
	local FOV = math.rad(Camera.FieldOfView)
	local Ratio = ScreenSize.X/ScreenSize.Y
	local PositionOffset = Offsets.Position + SpringOffsets.Position
	local RotationOffset = Offsets.Rotation + SpringOffsets.Rotation
	local SizeOffset = Offsets.Size + SpringOffsets.Size
	local OffsetRotation = CFrame.Angles(RotationOffset.X, RotationOffset.Y, RotationOffset.Z)
	local SizeX = SizeOffset.X*(Ratio)/FOV
	local SizeY = SizeOffset.Y*(Ratio)/FOV
	local PosX = PositionOffset.X*(Ratio)/FOV
	local PosY = PositionOffset.Y*(Ratio)/FOV
	local FinalOffset = Camera.CFrame * CFrame.new(PosX, PosY, PositionOffset.Z)
	GUIObject.CFrame = FinalOffset * CFrame.Angles(0, math.rad(180), 0)
	GUIObject.Size = Vector3.new(SizeX, SizeY, .1)

return GUI3D

Not sure how to solve this but maybe use viewport frames instead

Nevermind, I just had to divide my offset and screensize

local PosX = (ScreenSize.X/(PositionOffset.X))
local PosY = (ScreenSize.Y/(PositionOffset.Y))

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