Do you want to create awesome, phighting-esque 3D UI without the hassle of Renderstepped loops, arbitrary offsets, or god forbid UI resizing issues? Well boy, do I have the solution for you!
Screen3D was made with the goal of bridging the gap between 2D and 3D UI.
Usage:
First, create your Screen3D object.
This can be done for any 2D ScreenGui, but I’ll be using one that looks like this:
local mainUI : ScreenGui = path.to.your.ScreenGui
local screenGen = require(path.to.Screen3D.module)
local screen3D = screenGen.new(mainUI,5) --the second argument will be the distance of all surfaceguis from the camera
It looks like it did nothing, but after creating a Screen3D, every GuiObject inside it will be transformable into 3D UI.
Next up, using a 2D GuiObject (Frame, TextLabel, TextButton, ect…), get its corresponding Component3D:
local GuiObject2D = mainUI:WaitForChild('Frame')
local Component3D = screen3D:GetComponent3D(GuiObject2D)
Component3D:Enable()
For performance reasons, 2D UI objects aren’t converted into 3D UI until explicitly told to, with Component3D:Enable()
. This should only be called once and can be reversed with Component3D:Disable()
.
Although the UI looks the same, if you look at the explorer you’ll notice that your GuiObject is now a SurfaceGui!
OFFSETS 101
Let’s mess with our new 3D component a little!
All component3Ds have an offset
which can be both used to rotate and move them relative to their parent UI elements.
NOTE: offset
pivots UI elements on their anchorpoint.
For example:
You can set the offset to some static value:
local mainUI : ScreenGui = path.to.your.ScreenGui
local screenGen = require(path.to.Screen3D.module)
local screen3D = screenGen.new(mainUI,5)
local GuiObject2D = mainUI:WaitForChild('Frame')
local Component3D = screen3D:GetComponent3D(GuiObject2D)
Component3D:Enable()
Component3D.offset = CFrame.Angles(0,math.rad(10),0) --rotates your 3D UI element by 10 degrees
and/or change it to your heart’s content:
local mainUI : ScreenGui = path.to.your.ScreenGui
local screenGen = require(path.to.Screen3D.module)
local screen3D = screenGen.new(mainUI,5)
local GuiObject2D = mainUI:WaitForChild('Frame')
local Component3D = screen3D:GetComponent3D(GuiObject2D)
Component3D:Enable()
game:GetService('RunService').RenderStepped:Connect(function()
Component3D.offset = CFrame.Angles(0,math.sin(tick())/2,0) --spins your UI from -45 to +45 degrees
end)
3D UI NESTING
Now this is cool and all… But what if you put a SECOND 3D UI element inside of it and changed ITS offset too?
local mainUI : ScreenGui = path.to.your.ScreenGui
local screenGen = require(path.to.Screen3D.module)
local screen3D = screenGen.new(mainUI,5)
local GuiObject2D = mainUI:WaitForChild('Frame')
local InnerGuiObject = GuiObject2D:WaitForChild("A")
local Component3D = screen3D:GetComponent3D(GuiObject2D)
Component3D:Enable()
local InnerGuiObject3D = screen3D:GetComponent3D(InnerGuiObject)
InnerGuiObject3D:Enable()
InnerGuiObject3D.offset = CFrame.Angles(0,math.rad(25),0) --i chose to keep the offset static here for the sake of simplicity
game:GetService('RunService').RenderStepped:Connect(function()
Component3D.offset = CFrame.Angles(0,math.sin(tick()*5)/4,0) --sped up for the sake of the demo
end)
Nothing breaks down and everything works as expected!
The framework also tries to match the original 2D tree as much as possible, without compromising on usefulness:
This UI nesting can also be scaled essentially forever:
You can also nest 3D components within 2D elements, meaning you don’t have to :Enable() an entire tree of instances just to rotate one 3D frame.
play around with the demo world here:
3d_v2.rbxl (65.9 KB)
[OUTDATED]
or just grab the rbxm from github:
This module (along with an older, messier 3D module) is regularly used in unorthodox accounting and im finally allowed to publish it yippeee
Glory to goog.
-sun_6x and yqat