Hi all!
I made a confetti animation/effect that I’d like you share with you.
It’s a ModuleScript with a function that you can use to Emit
particles, you can input the number of particles (pieces of confetti) that you want. If you don’t input anything, it will default to 250.
Here is a demo:
Note that I have a sound included in the Emit function. You can delete this or just simply change the path.
There is also a second argument that you can add, giving the spawn point of the confetti (Udim2). However, this doesn’t change the direction they go (they always go upward). It wouldn’t be that hard to change though!
Here is the link to the module:
click here
Here is the code (not as recommended to copy and paste):
local Confetti = {}
Confetti.__index = Confetti
local TweenService = game:GetService("TweenService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local RunService = game:GetService("RunService")
local Players = game:GetService("Players")
local player = Players.LocalPlayer
local bonusSound = ReplicatedStorage:WaitForChild("ClientSounds").Bonus
local confettiShapes = {"Square", "Circle", "Triangle", "Diamond"}
local baseColors = {
Color3.fromRGB(255, 75, 75),
Color3.fromRGB(75, 255, 75),
Color3.fromRGB(75, 75, 255),
Color3.fromRGB(255, 255, 75),
Color3.fromRGB(255, 75, 255),
Color3.fromRGB(75, 255, 255)
}
function Confetti.new()
local self = setmetatable({}, Confetti)
self.ActiveConfetti = 0
self.activeEmitters = 0
return self
end
function Confetti:CreateConfettiPiece(spawnPos)
local confetti = Instance.new("Frame")
confetti.Name = "ConfettiPiece"
local size = math.random(24, 36)
confetti.Size = UDim2.new(0, size, 0, size)
confetti.BackgroundTransparency = 1
confetti.BorderSizePixel = 0
confetti.AnchorPoint = Vector2.new(0.5, 0.5)
if spawnPos and typeof(spawnPos) == "UDim2" then
confetti.Position = spawnPos
else
confetti.Position = UDim2.fromScale(math.random(0, 100)/100, math.random(-25, 125)/100)
end
local baseColor = baseColors[math.random(#baseColors)]
local brightnessFactor = math.random(95, 105) / 100
confetti.BackgroundColor3 = Color3.new(
math.clamp(baseColor.R * brightnessFactor, 0, 1),
math.clamp(baseColor.G * brightnessFactor, 0, 1),
math.clamp(baseColor.B * brightnessFactor, 0, 1)
)
local gradient = Instance.new("UIGradient")
gradient.Rotation = math.random(0, 360)
gradient.Color = ColorSequence.new{
ColorSequenceKeypoint.new(0, Color3.new(math.random(75, 100)/100, math.random(75, 100)/100, math.random(75, 100)/100)),
ColorSequenceKeypoint.new(1, Color3.new(math.random(75, 100)/100, math.random(75, 100)/100, math.random(75, 100)/100))
}
gradient.Parent = confetti
local shapeType = confettiShapes[math.random(#confettiShapes)]
local uiCorner = Instance.new("UICorner")
if shapeType == "Circle" then
uiCorner.CornerRadius = UDim.new(1, 0)
elseif shapeType == "Diamond" then
confetti.Rotation = 45
elseif shapeType == "Triangle" then
confetti.Size = UDim2.new(0, math.random(28, 38), 0, math.random(18, 28))
end
uiCorner.Parent = confetti
TweenService:Create(confetti, TweenInfo.new(0.5, Enum.EasingStyle.Quart, Enum.EasingDirection.InOut), {BackgroundTransparency = 0}):Play()
return confetti
end
function Confetti:Emit(amount, spawnPos : UDim2)
if typeof(amount) ~= "number" then amount = 250 end
local playerGui = player:FindFirstChildOfClass("PlayerGui")
local screenGui = playerGui:FindFirstChild("ConfettiScreenGui")
if not screenGui then
screenGui = Instance.new("ScreenGui")
screenGui.Name = "ConfettiGui"
screenGui.Parent = playerGui
screenGui.IgnoreGuiInset = true
end
self.activeEmitters = (self.activeEmitters or 0) + 1
bonusSound:Play()
for _ = 1, amount do
local confetti = self:CreateConfettiPiece(spawnPos)
confetti.Parent = screenGui
local velocityX, velocityY, gravity = math.random(-300, 300), math.random(-350, -200), 75
local rotationSpeed = math.random(-300, 300)
local startTime = tick()
local connection
connection = RunService.RenderStepped:Connect(function(deltaTime)
if not confetti.Parent then
connection:Disconnect()
return
end
local elapsedTime = tick() - startTime
local newX = confetti.Position.X.Scale + (velocityX * deltaTime / 400)
local newY = confetti.Position.Y.Scale + (velocityY * deltaTime / 400) + (0.5 * gravity * elapsedTime^2 / 3000)
confetti.Position = UDim2.new(newX, 0, math.min(newY, 1.3), 0)
confetti.Rotation += rotationSpeed * deltaTime + math.sin(elapsedTime * 2) * 0.5
if newY > 1.3 then
confetti:Destroy()
connection:Disconnect()
self.ActiveConfetti -= 1
end
end)
self.ActiveConfetti = (self.ActiveConfetti or 0) + 1
end
coroutine.wrap(function()
while self.ActiveConfetti > 0 do task.wait(1) end
self.activeEmitters -= 1
if self.activeEmitters ~= 0 then return end
screenGui:Destroy()
end)()
end
return Confetti
Ask me questions if you have any, I’d be happy to answer.
Thanks,
7eoeb