Screen3D - A 3D UI framework that just works

They are currently disabled, I’ve changed it and it does absolutely nothing

Yea , These special types for surface GUI are supposed to be an beta feature that was avaliable for a short months and then got removed by optimizations errors :sob:

I don’t know about this until i discovered the web saying about that

To be specific:

Velocity = ?

sensitivity_constant1 = ?
sensitivity_constant2 = ?

min_angle = ?
max_angle = ?

I cant seem to reproduce functionality at all. I need the values for these variables to make it work. I can take it from there

I was able to produce a rough version of what you have given me.

	local LerpSpeed = 2
	local SensConst1 = .2
		
	RunService.RenderStepped:Connect(function(DeltaTime)
		
		local RootPartAssemblyLinearVelocity = Knit.Player.Character.HumanoidRootPart.AssemblyLinearVelocity
		
		local RelativeVelocity = Camera.CFrame.Rotation:ToObjectSpace(CFrame.new(RootPartAssemblyLinearVelocity * SensConst1 )).Position
		local lerp_alpha = math.min(DeltaTime * LerpSpeed, 1) --avoids low framerate jank'
		
		ThreeDHealthBarGUI.rootOffset = ThreeDHealthBarGUI.rootOffset:Lerp(CFrame.new(RelativeVelocity), lerp_alpha)
		
	end)

However, I would like to know if there is a method to keep the rootoffset limited to a certain range as for it not to go offscreen.

1 More thing…

The method im currently using (modified version of what you gave me) is incredibly unperformant.

It uses up to 4% activity rate at /555s Update rate.

Is there a way to improve the performance?

glory to goog.
god bless goog.

I love those games!
Thats really impressive, I never even realised.

oh yeah right i forgot about that part, you could probably just do a basic magnitude clamp

so something that looks like

local max_velocity : number = 20 --or anything

local RelativeVelocity : Vector3 = [ ... ]

if RelativeVelocity.Magnitude ~= 0 then
      RelativeVelocity = math.min(max_velocity, RelativeVelocity.Magnitude  ) * RelativeVelocity.Unit
end

Hello!
I must say this Module is very nice, thanks for making it! However I have seen some trouble, whenever my field of view changed the UI begins to move (Seen in the video below) Is there any way to fix it / make it stay how it is?

3 Likes

No, cuz SurfaceGui is displayed in Workspace Viewport, you can’t change that. And you can’t sadly use diffirent viewport for that.

You could probably tween a property to match the change in object to viewport size.

that seems to be due to the nature of how offsets work because angles look different under different fovs

i’ll try adding some kind of setting in future versions that assumes all offsets are made in the default fov to fix stuff like that

this won’t be happening in the near future though because i have NO clue how fov distorts orientations, if one of you geniuses figures it out please make a pull request lmao

On it sir!

(I might be medicore at coding but I’m excellent at any form of science)

added REALLY BASIC and REALLY FLAWED and REALLY JANKY fov independency support in the dev branch for this:

it only works when rx and ry are set independently for offsets
CFrame.Angles(? , 0, 0) works
CFrame.Angles(0 , ?, 0) works
CFrame.Angles(? , ?, 0) doesn’t

and it’s toggled on by setting Component3D.fovIndependant to true

DO NOT USE THIS UNLESS YOU ABSOLUTELY NEED IT, IT HAS WEIRD SIDE EFFECTS AND BUGS

as usual, if someone wants to fix this, feel free to make a pull request lol

3 Likes

Nope, Roblox engine is not very likable when it comes to things like this. Cant find a single solution (That fully solves the problem).

(Im accursedheaven btw)

	RunService.RenderStepped:Connect(function(DeltaTime)

		local RootPartAssemblyLinearVelocity = Knit.Player.Character.HumanoidRootPart.AssemblyLinearVelocity

		if RootPartAssemblyLinearVelocity == 0 then
			return
		end

		local RelativeVelocity = Camera.CFrame.Rotation:ToObjectSpace(CFrame.new(RootPartAssemblyLinearVelocity * Sensitivity)).Position
		local LerpAlpha = math.min(DeltaTime * LerpSpeed, 1)

		if RelativeVelocity.Magnitude ~= 0 then
			RelativeVelocity = math.min(MaxVelocity, RelativeVelocity.Magnitude  ) * RelativeVelocity.Unit
		end

		ThreeDStaminaBarGUI.rootOffset = ThreeDStaminaBarGUI.rootOffset:Lerp(CFrame.new(RelativeVelocity), LerpAlpha)

	end)

This is pretty good, anyway to increase performance?

Doesn’t work :pensive:

Supposed to look like:

Ingame (entropy meter completely disappears…)

Code:
image
Honestly I really wanna use this module but right now it just kinda doesn’t work :slightly_frowning_face:

Any help from anyone who knows what might be happening would be appreicated, happy to give any additional info regarding htis :heart:

Noticed a bug ( I think).

The “3D” element disappears if you respawn.

Code:

--//Services
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local RunService = game:GetService("RunService")

--//Local Variables
local Camera = workspace.CurrentCamera

--//Modules
local Modules = ReplicatedStorage.Modules

local Screen3D = require(Modules.UI.Components.Screen3D)

local Information = require(ReplicatedStorage.Shared.Information)
local UserData = require(ReplicatedStorage.Shared.UserData)

--//Information
local MovesetInformation = Information.Movesets
local ChihiroInformation = MovesetInformation.Chihiro
local KunishigeInformation = MovesetInformation.Kunishige

local GlobalData = UserData.Global

--//Main 
local Knit = require(ReplicatedStorage.Packages.Knit)

--//UI
local PlayerGui: PlayerGui = Knit.Player.PlayerGui

local HotbarGUI: GuiBase = PlayerGui:WaitForChild("Hotbar")

local HotbarFrame: Frame = HotbarGUI:WaitForChild("Hotbar")
local TipCanvas: CanvasGroup = HotbarFrame:WaitForChild("Tip")

local SkillSlots = HotbarFrame:WaitForChild("SkillSlots")

local SkillSlot1: TextButton = SkillSlots:WaitForChild("1")
local SkillSlot2: TextButton = SkillSlots:WaitForChild("2")
local SkillSlot3: TextButton = SkillSlots:WaitForChild("3")
local SkillSlot4: TextButton = SkillSlots:WaitForChild("4")

local SkillSlotText1: TextLabel = SkillSlot1:WaitForChild("ButtonText")
local SkillSlotText2: TextLabel = SkillSlot2:WaitForChild("ButtonText")
local SkillSlotText3: TextLabel = SkillSlot3:WaitForChild("ButtonText")
local SkillSlotText4: TextLabel = SkillSlot4:WaitForChild("ButtonText")

--//3D UI
local ThreeDHotbarGUI = Screen3D.new(HotbarGUI, 5)

local ThreeDHotbarFrame = ThreeDHotbarGUI:GetComponent3D(HotbarFrame)
local ThreeDTipCanvas = ThreeDHotbarGUI:GetComponent3D(TipCanvas)

local ThreeDSkillSlots = ThreeDHotbarGUI:GetComponent3D(SkillSlots)

local ThreeDSkillSlot1 = ThreeDHotbarGUI:GetComponent3D(SkillSlot1)
local ThreeDSkillSlot2 = ThreeDHotbarGUI:GetComponent3D(SkillSlot2)
local ThreeDSkillSlot3 = ThreeDHotbarGUI:GetComponent3D(SkillSlot3)
local ThreeDSkillSlot4 = ThreeDHotbarGUI:GetComponent3D(SkillSlot4)

local ThreeDSkillSlotText1 = ThreeDHotbarGUI:GetComponent3D(SkillSlotText1)
local ThreeDSkillSlotText2 = ThreeDHotbarGUI:GetComponent3D(SkillSlotText2)
local ThreeDSkillSlotText3 = ThreeDHotbarGUI:GetComponent3D(SkillSlotText3)
local ThreeDSkillSlotText4 = ThreeDHotbarGUI:GetComponent3D(SkillSlotText4)

--//Settings
local LerpSpeed = 2
local Sensitivity = .02

local MaxVelocity : number = 1 --or anything


--//Module
local HotBarController = Knit.CreateController  {
	Name = "HotBarController",
	
	CurrentMoveset = nil,
}

--//Start
function HotBarController:KnitStart()
	
	--//Initial
	self:Create3DHotbar()
	
	Knit.Player.CharacterAdded:Connect(function(Character)
		self:Create3DHotbar()
	end)

end

--//Methods
function HotBarController:Create3DHotbar()
	
	--//Enable
	ThreeDHotbarFrame:Enable()
	ThreeDTipCanvas:Enable()

	ThreeDSkillSlots:Enable()

	ThreeDSkillSlot1:Enable()
	ThreeDSkillSlot2:Enable()
	ThreeDSkillSlot3:Enable()
	ThreeDSkillSlot4:Enable()

	ThreeDSkillSlotText1:Enable()
	ThreeDSkillSlotText2:Enable()
	ThreeDSkillSlotText3:Enable()
	ThreeDSkillSlotText4:Enable()

	--//Inital Offset
	ThreeDHotbarFrame.offset = CFrame.Angles(0,math.rad(10),0) 
	ThreeDTipCanvas.offset = CFrame.Angles(0,math.rad(10),0) 

	ThreeDSkillSlots.offset = CFrame.Angles(0,math.rad(10),0) 

	ThreeDSkillSlot1.offset = CFrame.Angles(0,math.rad(10),0) 
	ThreeDSkillSlot2.offset = CFrame.Angles(0,math.rad(10),0) 
	ThreeDSkillSlot3.offset = CFrame.Angles(0,math.rad(10),0) 
	ThreeDSkillSlot4.offset = CFrame.Angles(0,math.rad(10),0) 

	ThreeDSkillSlotText1.offset = CFrame.Angles(0,math.rad(10),0) 
	ThreeDSkillSlotText2.offset = CFrame.Angles(0,math.rad(10),0) 
	ThreeDSkillSlotText3.offset = CFrame.Angles(0,math.rad(10),0) 
	ThreeDSkillSlotText4.offset = CFrame.Angles(0,math.rad(10),0) 
	
	task.spawn(function()
		
		local Connection = RunService.RenderStepped:Connect(function(DeltaTime)

			local RootPartAssemblyLinearVelocity = Knit.Player.Character.HumanoidRootPart.AssemblyLinearVelocity

			if RootPartAssemblyLinearVelocity == 0 then
				return
			end

			local RelativeVelocity = Camera.CFrame.Rotation:ToObjectSpace(CFrame.new(RootPartAssemblyLinearVelocity * Sensitivity)).Position
			local LerpAlpha = math.min(DeltaTime * LerpSpeed, 1)

			if RelativeVelocity.Magnitude ~= 0 then
				RelativeVelocity = math.min(MaxVelocity, RelativeVelocity.Magnitude  ) * RelativeVelocity.Unit
			end

			ThreeDHotbarGUI.rootOffset = ThreeDHotbarGUI.rootOffset:Lerp(CFrame.new(RelativeVelocity), LerpAlpha)

		end)
		
	end)
	
end

	
function HotBarController:SetHotbarEnabled(Boolean: boolean)

	for _,SurfaceGui: SurfaceGui in HotbarGUI:GetDescendants() do

		if SurfaceGui:IsA("SurfaceGui") then
			SurfaceGui.Enabled = Boolean
		end

	end

end

function HotBarController:SetSkillTexts(CharacterName: string)
	
	if CharacterName == "Chihiro" then

		self.CurrentMoveset = "Chihiro"

		SkillSlotText1.Text = ChihiroInformation.Skills.One
		SkillSlotText2.Text = ChihiroInformation.Skills.Two
		SkillSlotText3.Text = ChihiroInformation.Skills.Three
		SkillSlotText4.Text = ChihiroInformation.Skills.Four


	elseif CharacterName == "Kunishige" then

		self.CurrentMoveset = "Kunishige"

		SkillSlotText1.Text = KunishigeInformation.Skills.One
		SkillSlotText2.Text = KunishigeInformation.Skills.Two
		SkillSlotText3.Text = KunishigeInformation.Skills.Three
		SkillSlotText4.Text = KunishigeInformation.Skills.Four

	end
	
end



return HotBarController

Disable the ResetOnSpawn property of your base gui if you dont want the 3d ui to refresh when the player respawns

its an intentional choice i made when designing the ui framework to make sure it acts as closely as possible to its 2d counterpart

Ahhh, I sort of just assumed ResetOnSpawn wouldn’t affect it for some reason…

But honestly, great thinking!

Unrelated but,
Do you mind if I credit you in my game for the 3d framework?