Build complex, animated UI systems with custom frameworks.
Create a reusable UI component system.
local UIComponent = {}
UIComponent.__index = UIComponent
function UIComponent.new(parent, properties)
local self = setmetatable({}, UIComponent)
self.instance = Instance.new("Frame")
self.instance.Parent = parent
self.children = {}
self.state = {}
-- Apply properties
for property, value in pairs(properties or {}) do
self.instance[property] = value
end
return self
end
function UIComponent:setState(newState)
for key, value in pairs(newState) do
self.state[key] = value
end
self:render()
end
function UIComponent:render()
-- Override in child classes
end
function UIComponent:addChild(child)
table.insert(self.children, child)
return child
end
function UIComponent:destroy()
for _, child in ipairs(self.children) do
child:destroy()
end
self.instance:Destroy()
end
Base component class with state management and lifecycle methods.
local Button = setmetatable({}, {__index = UIComponent})
Button.__index = Button
function Button.new(parent, properties)
local self = setmetatable(UIComponent.new(parent, properties), Button)
self.textLabel = Instance.new("TextLabel")
self.textLabel.Size = UDim2.new(1, 0, 1, 0)
self.textLabel.BackgroundTransparency = 1
self.textLabel.TextColor3 = Color3.new(1, 1, 1)
self.textLabel.Parent = self.instance
-- Hover effects
self.instance.MouseEnter:Connect(function()
self:onHover()
end)
self.instance.MouseLeave:Connect(function()
self:onLeave()
end)
self.instance.MouseButton1Click:Connect(function()
if self.onClick then
self:onClick()
end
end)
return self
end
function Button:setText(text)
self.textLabel.Text = text
end
function Button:onHover()
self.instance.BackgroundColor3 = Color3.fromRGB(100, 100, 255)
end
function Button:onLeave()
self.instance.BackgroundColor3 = Color3.fromRGB(70, 70, 200)
end
-- Usage
local myButton = Button.new(screenGui, {
Size = UDim2.new(0, 200, 0, 50),
Position = UDim2.new(0.5, -100, 0.5, -25),
BackgroundColor3 = Color3.fromRGB(70, 70, 200)
})
myButton:setText("Click Me!")
myButton.onClick = function()
print("Button clicked!")
end
Reusable button component with hover effects and click handling.
Create smooth, complex UI animations.
local TweenService = game:GetService("TweenService")
local AnimationQueue = {}
AnimationQueue.__index = AnimationQueue
function AnimationQueue.new()
local self = setmetatable({}, AnimationQueue)
self.queue = {}
self.isPlaying = false
return self
end
function AnimationQueue:add(guiObject, tweenInfo, goals)
table.insert(self.queue, {
object = guiObject,
info = tweenInfo,
goals = goals
})
return self -- For chaining
end
function AnimationQueue:play(callback)
if self.isPlaying then return end
self.isPlaying = true
local index = 1
local function playNext()
if index > #self.queue then
self.isPlaying = false
if callback then callback() end
return
end
local anim = self.queue[index]
local tween = TweenService:Create(anim.object, anim.info, anim.goals)
tween.Completed:Connect(function()
index = index + 1
playNext()
end)
tween:Play()
end
playNext()
end
-- Usage
local queue = AnimationQueue.new()
queue:add(frame1, TweenInfo.new(0.5), {Position = UDim2.new(0.5, 0, 0.5, 0)})
queue:add(frame2, TweenInfo.new(0.3), {Size = UDim2.new(0, 200, 0, 200)})
queue:add(frame3, TweenInfo.new(0.4), {BackgroundTransparency = 0})
queue:play(function()
print("All animations complete!")
end)
Queue system for sequential animations.
local NotificationSystem = {}
function NotificationSystem.show(message, duration)
local screenGui = game.Players.LocalPlayer.PlayerGui:FindFirstChild("Notifications")
if not screenGui then
screenGui = Instance.new("ScreenGui")
screenGui.Name = "Notifications"
screenGui.Parent = game.Players.LocalPlayer.PlayerGui
end
-- Create notification
local notification = Instance.new("Frame")
notification.Size = UDim2.new(0, 300, 0, 60)
notification.Position = UDim2.new(1, 320, 0.9, 0) -- Start off-screen
notification.BackgroundColor3 = Color3.fromRGB(40, 40, 40)
notification.BorderSizePixel = 0
notification.Parent = screenGui
-- Rounded corners
local corner = Instance.new("UICorner")
corner.CornerRadius = UDim.new(0, 8)
corner.Parent = notification
-- Message text
local textLabel = Instance.new("TextLabel")
textLabel.Size = UDim2.new(1, -20, 1, 0)
textLabel.Position = UDim2.new(0, 10, 0, 0)
textLabel.BackgroundTransparency = 1
textLabel.Text = message
textLabel.TextColor3 = Color3.new(1, 1, 1)
textLabel.TextXAlignment = Enum.TextXAlignment.Left
textLabel.Parent = notification
-- Animate in
local tweenIn = TweenService:Create(
notification,
TweenInfo.new(0.5, Enum.EasingStyle.Back, Enum.EasingDirection.Out),
{Position = UDim2.new(1, -320, 0.9, 0)}
)
tweenIn:Play()
-- Wait and animate out
task.wait(duration or 3)
local tweenOut = TweenService:Create(
notification,
TweenInfo.new(0.3, Enum.EasingStyle.Quad, Enum.EasingDirection.In),
{Position = UDim2.new(1, 320, 0.9, 0)}
)
tweenOut.Completed:Connect(function()
notification:Destroy()
end)
tweenOut:Play()
end
-- Usage
NotificationSystem.show("Welcome to the game!", 3)
NotificationSystem.show("Quest completed!", 2)
Animated notification system with slide-in/out effects.
Make UI adapt to different screen sizes.
-- Use UDim2.fromScale for responsive sizing
local function createResponsiveFrame(parent)
local frame = Instance.new("Frame")
frame.Size = UDim2.fromScale(0.8, 0.6) -- 80% width, 60% height
frame.Position = UDim2.fromScale(0.1, 0.2) -- Centered with margin
frame.Parent = parent
-- Add UIAspectRatioConstraint for consistent proportions
local aspect = Instance.new("UIAspectRatioConstraint")
aspect.AspectRatio = 16/9
aspect.Parent = frame
return frame
end
-- Use UISizeConstraint for limits
local function addSizeConstraints(guiObject)
local constraint = Instance.new("UISizeConstraint")
constraint.MinSize = Vector2.new(200, 100)
constraint.MaxSize = Vector2.new(800, 600)
constraint.Parent = guiObject
end
Use Scale instead of Offset for responsive layouts.
Create an animated health bar UI component.
-- Create a health bar that animates when health changes
local HealthBar = setmetatable({}, {__index = UIComponent})
HealthBar.__index = HealthBar
function HealthBar.new(parent, maxHealth)
local self = setmetatable(UIComponent.new(parent, {
Size = UDim2.new(0, 200, 0, 30),
BackgroundColor3 = Color3.fromRGB(50, 50, 50)
}), HealthBar)
self.fill = Instance.new("Frame")
self.fill.Size = UDim2.new(1, 0, 1, 0)
self.fill.BackgroundColor3 = Color3.fromRGB(0, 255, 0)
self.fill.BorderSizePixel = 0
self.fill.Parent = self.instance
self.maxHealth = maxHealth
self.currentHealth = maxHealth
return self
end
function HealthBar:setHealth(health)
self.currentHealth = math.clamp(health, 0, self.maxHealth)
local percentage = self.currentHealth / self.maxHealth
TweenService:Create(
self.fill,
TweenInfo.new(0.3),
{Size = UDim2.new(percentage, 0, 1, 0)}
):Play()
-- Change color based on health
local color
if percentage > 0.5 then
color = Color3.fromRGB(0, 255, 0)
elseif percentage > 0.25 then
color = Color3.fromRGB(255, 255, 0)
else
color = Color3.fromRGB(255, 0, 0)
end
self.fill.BackgroundColor3 = color
end
Continue your learning journey