vfx-effects

Roblox Visual Effects (VFX)

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "vfx-effects" with this command: npx skills add taozhuo/game-dev-skills/taozhuo-game-dev-skills-vfx-effects

Roblox Visual Effects (VFX)

When implementing VFX, use these patterns for impactful and performant effects.

Particle Effects

Anime Hit VFX

local function createHitEffect(position, direction, intensity) intensity = intensity or 1

-- Impact flash
local flash = Instance.new("Part")
flash.Shape = Enum.PartType.Ball
flash.Size = Vector3.new(0.1, 0.1, 0.1)
flash.Position = position
flash.Anchored = true
flash.CanCollide = false
flash.Material = Enum.Material.Neon
flash.Color = Color3.new(1, 1, 1)
flash.Parent = workspace.Effects

-- Scale up and fade
local tweenInfo = TweenInfo.new(0.15, Enum.EasingStyle.Quad, Enum.EasingDirection.Out)
TweenService:Create(flash, tweenInfo, {
    Size = Vector3.new(3, 3, 3) * intensity,
    Transparency = 1
}):Play()

-- Radial lines (speedlines)
local numLines = 8
for i = 1, numLines do
    local angle = (i / numLines) * math.pi * 2
    local lineDir = Vector3.new(math.cos(angle), 0, math.sin(angle))

    local line = Instance.new("Part")
    line.Size = Vector3.new(0.1, 0.1, 2)
    line.CFrame = CFrame.lookAt(position, position + lineDir) * CFrame.new(0, 0, -1)
    line.Anchored = true
    line.CanCollide = false
    line.Material = Enum.Material.Neon
    line.Color = Color3.new(1, 0.9, 0.8)
    line.Parent = workspace.Effects

    TweenService:Create(line, TweenInfo.new(0.2), {
        Size = Vector3.new(0.05, 0.05, 5) * intensity,
        CFrame = line.CFrame * CFrame.new(0, 0, -3),
        Transparency = 1
    }):Play()

    Debris:AddItem(line, 0.3)
end

-- Screen shake
shakeCamera(0.3, intensity * 5)

Debris:AddItem(flash, 0.2)

end

Slash Trail

local function createSlashTrail(weapon, duration) local attachment0 = weapon:FindFirstChild("TrailAttachment0") local attachment1 = weapon:FindFirstChild("TrailAttachment1")

if not attachment0 or not attachment1 then
    -- Create attachments at blade ends
    attachment0 = Instance.new("Attachment")
    attachment0.Name = "TrailAttachment0"
    attachment0.Position = Vector3.new(0, 0, 2)  -- Tip
    attachment0.Parent = weapon

    attachment1 = Instance.new("Attachment")
    attachment1.Name = "TrailAttachment1"
    attachment1.Position = Vector3.new(0, 0, 0)  -- Base
    attachment1.Parent = weapon
end

local trail = Instance.new("Trail")
trail.Attachment0 = attachment0
trail.Attachment1 = attachment1
trail.Lifetime = 0.3
trail.MinLength = 0
trail.FaceCamera = true
trail.Color = ColorSequence.new({
    ColorSequenceKeypoint.new(0, Color3.new(1, 1, 1)),
    ColorSequenceKeypoint.new(1, Color3.new(0.8, 0.8, 1))
})
trail.Transparency = NumberSequence.new({
    NumberSequenceKeypoint.new(0, 0),
    NumberSequenceKeypoint.new(0.5, 0.3),
    NumberSequenceKeypoint.new(1, 1)
})
trail.WidthScale = NumberSequence.new({
    NumberSequenceKeypoint.new(0, 1),
    NumberSequenceKeypoint.new(1, 0.2)
})
trail.Parent = weapon

-- Disable after duration
task.delay(duration, function()
    trail.Enabled = false
    Debris:AddItem(trail, trail.Lifetime)
end)

return trail

end

Aura Effect

local function createAura(character, color, intensity) local hrp = character:FindFirstChild("HumanoidRootPart") if not hrp then return end

local attachment = Instance.new("Attachment")
attachment.Parent = hrp

local particles = Instance.new("ParticleEmitter")
particles.Color = ColorSequence.new(color)
particles.Size = NumberSequence.new({
    NumberSequenceKeypoint.new(0, 0.5),
    NumberSequenceKeypoint.new(0.5, 1),
    NumberSequenceKeypoint.new(1, 0)
})
particles.Transparency = NumberSequence.new({
    NumberSequenceKeypoint.new(0, 0.5),
    NumberSequenceKeypoint.new(1, 1)
})
particles.Lifetime = NumberRange.new(0.5, 1)
particles.Rate = 50 * intensity
particles.Speed = NumberRange.new(2, 4)
particles.SpreadAngle = Vector2.new(180, 180)
particles.Acceleration = Vector3.new(0, 5, 0)
particles.EmissionDirection = Enum.NormalId.Top
particles.Parent = attachment

-- Point light for glow
local light = Instance.new("PointLight")
light.Color = color
light.Brightness = intensity
light.Range = 10
light.Parent = hrp

return {
    stop = function()
        particles.Enabled = false
        TweenService:Create(light, TweenInfo.new(0.5), {Brightness = 0}):Play()
        Debris:AddItem(attachment, 1)
        Debris:AddItem(light, 0.5)
    end
}

end

Camera Effects

Screen Shake

local ShakeModule = {} local currentShake = Vector3.new()

function ShakeModule.shake(duration, magnitude, frequency) frequency = frequency or 20

local startTime = os.clock()
local conn
conn = RunService.RenderStepped:Connect(function()
    local elapsed = os.clock() - startTime
    if elapsed > duration then
        currentShake = Vector3.new()
        conn:Disconnect()
        return
    end

    -- Decay over time
    local decay = 1 - (elapsed / duration)
    local shake = magnitude * decay

    -- Random offset
    currentShake = Vector3.new(
        (math.random() - 0.5) * 2 * shake,
        (math.random() - 0.5) * 2 * shake,
        0
    )
end)

end

function ShakeModule.getOffset() return currentShake end

-- Apply in camera update RunService.RenderStepped:Connect(function() local offset = ShakeModule.getOffset() camera.CFrame = camera.CFrame * CFrame.new(offset) end)

Hit Stop (Frame Freeze)

local function hitStop(duration) duration = duration or 0.05

-- Store original time scale
local originalSpeed = 1

-- Slow down animations
for _, player in ipairs(Players:GetPlayers()) do
    local character = player.Character
    if character then
        local humanoid = character:FindFirstChildOfClass("Humanoid")
        if humanoid then
            local animator = humanoid:FindFirstChildOfClass("Animator")
            if animator then
                for _, track in ipairs(animator:GetPlayingAnimationTracks()) do
                    track:AdjustSpeed(0.01)
                end
            end
        end
    end
end

task.wait(duration)

-- Restore
for _, player in ipairs(Players:GetPlayers()) do
    local character = player.Character
    if character then
        local humanoid = character:FindFirstChildOfClass("Humanoid")
        if humanoid then
            local animator = humanoid:FindFirstChildOfClass("Animator")
            if animator then
                for _, track in ipairs(animator:GetPlayingAnimationTracks()) do
                    track:AdjustSpeed(1)
                end
            end
        end
    end
end

end

Zoom Punch Effect

local function zoomPunch(intensity, duration) intensity = intensity or 5 duration = duration or 0.1

local camera = workspace.CurrentCamera
local originalFOV = camera.FieldOfView

-- Quick zoom in
TweenService:Create(camera, TweenInfo.new(duration * 0.3, Enum.EasingStyle.Quad, Enum.EasingDirection.Out), {
    FieldOfView = originalFOV - intensity
}):Play()

task.wait(duration * 0.3)

-- Slower return
TweenService:Create(camera, TweenInfo.new(duration * 0.7, Enum.EasingStyle.Quad, Enum.EasingDirection.Out), {
    FieldOfView = originalFOV
}):Play()

end

Lighting Effects

Dynamic Muzzle Flash

local function muzzleFlash(attachment) -- Light local light = Instance.new("PointLight") light.Color = Color3.new(1, 0.9, 0.5) light.Brightness = 5 light.Range = 15 light.Parent = attachment

-- Flash particle
local flash = Instance.new("ParticleEmitter")
flash.Texture = "rbxassetid://123456789"  -- Muzzle flash texture
flash.Size = NumberSequence.new(1.5)
flash.Lifetime = NumberRange.new(0.05)
flash.Rate = 0
flash.Speed = NumberRange.new(0)
flash.Parent = attachment

flash:Emit(1)

-- Fade light
TweenService:Create(light, TweenInfo.new(0.1), {Brightness = 0}):Play()

Debris:AddItem(light, 0.15)
Debris:AddItem(flash, 0.1)

end

Lightning Flash

local function lightningFlash() local lighting = game:GetService("Lighting") local originalAmbient = lighting.Ambient

-- Flash white
lighting.Ambient = Color3.new(1, 1, 1)

task.wait(0.05)
lighting.Ambient = originalAmbient
task.wait(0.1)
lighting.Ambient = Color3.new(0.8, 0.8, 0.8)
task.wait(0.05)
lighting.Ambient = originalAmbient

end

Mesh & Material Effects

Dissolve Effect

local function dissolve(part, duration) -- Create a dissolve texture local surfaceGui = Instance.new("SurfaceGui") surfaceGui.Face = Enum.NormalId.Front surfaceGui.LightInfluence = 0

local frame = Instance.new("Frame")
frame.Size = UDim2.new(1, 0, 1, 0)
frame.BackgroundTransparency = 1
frame.Parent = surfaceGui

local gradient = Instance.new("UIGradient")
gradient.Rotation = 90
gradient.Parent = frame

surfaceGui.Parent = part

-- Animate gradient offset
local startTime = os.clock()
local conn
conn = RunService.RenderStepped:Connect(function()
    local elapsed = os.clock() - startTime
    local t = elapsed / duration

    if t >= 1 then
        part:Destroy()
        conn:Disconnect()
        return
    end

    gradient.Offset = Vector2.new(0, t * 2 - 1)
    part.Transparency = t
end)

end

Outline Effect

local function addOutline(character, color, thickness) thickness = thickness or 0.05

for _, part in ipairs(character:GetDescendants()) do
    if part:IsA("BasePart") and part.Name ~= "HumanoidRootPart" then
        local outline = part:Clone()
        outline.Name = "Outline"
        outline.Size = part.Size + Vector3.new(thickness, thickness, thickness)
        outline.Material = Enum.Material.SmoothPlastic
        outline.Color = color
        outline.CanCollide = false
        outline.Massless = true
        outline.Transparency = 0

        local weld = Instance.new("WeldConstraint")
        weld.Part0 = part
        weld.Part1 = outline
        weld.Parent = outline

        outline.Parent = part
    end
end

end

UI Visual Effects

Damage Numbers

local function showDamageNumber(position, damage, isCrit) local billboardGui = Instance.new("BillboardGui") billboardGui.Size = UDim2.new(0, 100, 0, 50) billboardGui.StudsOffset = Vector3.new(0, 2, 0) billboardGui.Adornee = nil billboardGui.AlwaysOnTop = true

local label = Instance.new("TextLabel")
label.Size = UDim2.new(1, 0, 1, 0)
label.BackgroundTransparency = 1
label.Text = tostring(math.floor(damage))
label.TextColor3 = isCrit and Color3.new(1, 0.8, 0) or Color3.new(1, 1, 1)
label.TextStrokeTransparency = 0
label.TextStrokeColor3 = Color3.new(0, 0, 0)
label.TextScaled = true
label.Font = Enum.Font.GothamBold
label.Parent = billboardGui

-- Position in world
local part = Instance.new("Part")
part.Anchored = true
part.CanCollide = false
part.Transparency = 1
part.Size = Vector3.new(0.1, 0.1, 0.1)
part.Position = position
part.Parent = workspace.Effects

billboardGui.Adornee = part
billboardGui.Parent = part

-- Animate: rise and fade
local startY = position.Y
local startTime = os.clock()

local conn
conn = RunService.RenderStepped:Connect(function()
    local elapsed = os.clock() - startTime
    local t = elapsed / 1

    if t >= 1 then
        part:Destroy()
        conn:Disconnect()
        return
    end

    -- Rise with easing
    local easeT = 1 - (1 - t) ^ 2
    part.Position = Vector3.new(position.X, startY + easeT * 3, position.Z)

    -- Fade out
    label.TextTransparency = t
    label.TextStrokeTransparency = t

    -- Scale pop for crits
    if isCrit and t < 0.2 then
        local scale = 1 + math.sin(t * 5 * math.pi) * 0.3
        label.TextSize = 24 * scale
    end
end)

end

Cooldown Sweep

local function createCooldownUI(button, cooldownDuration) local overlay = Instance.new("Frame") overlay.Name = "CooldownOverlay" overlay.Size = UDim2.new(1, 0, 1, 0) overlay.BackgroundColor3 = Color3.new(0, 0, 0) overlay.BackgroundTransparency = 0.5 overlay.Parent = button

local gradient = Instance.new("UIGradient")
gradient.Rotation = -90
gradient.Transparency = NumberSequence.new({
    NumberSequenceKeypoint.new(0, 0),
    NumberSequenceKeypoint.new(0.5, 0),
    NumberSequenceKeypoint.new(0.501, 1),
    NumberSequenceKeypoint.new(1, 1)
})
gradient.Parent = overlay

-- Animate
local startTime = os.clock()
local conn
conn = RunService.RenderStepped:Connect(function()
    local elapsed = os.clock() - startTime
    local t = elapsed / cooldownDuration

    if t >= 1 then
        overlay:Destroy()
        conn:Disconnect()
        return
    end

    -- Rotate gradient to create sweep effect
    gradient.Rotation = -90 + (t * 360)
end)

end

Advanced VFX

Beam Weapon

local function createBeam(startAttachment, endPosition, duration) local endPart = Instance.new("Part") endPart.Anchored = true endPart.CanCollide = false endPart.Transparency = 1 endPart.Size = Vector3.new(0.1, 0.1, 0.1) endPart.Position = endPosition endPart.Parent = workspace.Effects

local endAttachment = Instance.new("Attachment")
endAttachment.Parent = endPart

local beam = Instance.new("Beam")
beam.Attachment0 = startAttachment
beam.Attachment1 = endAttachment
beam.Width0 = 0.5
beam.Width1 = 0.3
beam.FaceCamera = true
beam.Color = ColorSequence.new(Color3.new(1, 0, 0))
beam.Transparency = NumberSequence.new(0)
beam.LightEmission = 1
beam.LightInfluence = 0
beam.TextureSpeed = 5
beam.Parent = startAttachment

-- Fade out
task.delay(duration * 0.7, function()
    TweenService:Create(beam, TweenInfo.new(duration * 0.3), {
        Transparency = NumberSequence.new(1)
    }):Play()
end)

Debris:AddItem(endPart, duration)
Debris:AddItem(beam, duration)

return beam

end

Lightning Chain

local function createLightningChain(startPos, endPos, segments) segments = segments or 8

local parts = {}
local direction = endPos - startPos
local segmentLength = direction.Magnitude / segments

for i = 1, segments do
    local t1 = (i - 1) / segments
    local t2 = i / segments

    local p1 = startPos + direction * t1
    local p2 = startPos + direction * t2

    -- Add random offset (except for endpoints)
    if i > 1 then
        local jitter = segmentLength * 0.5
        p1 = p1 + Vector3.new(
            (math.random() - 0.5) * jitter,
            (math.random() - 0.5) * jitter,
            (math.random() - 0.5) * jitter
        )
    end

    local segment = Instance.new("Part")
    segment.Anchored = true
    segment.CanCollide = false
    segment.Material = Enum.Material.Neon
    segment.Color = Color3.new(0.7, 0.8, 1)

    local dist = (p2 - p1).Magnitude
    segment.Size = Vector3.new(0.1, 0.1, dist)
    segment.CFrame = CFrame.lookAt((p1 + p2) / 2, p2)
    segment.Parent = workspace.Effects

    table.insert(parts, segment)
end

-- Quick flash and fade
task.delay(0.05, function()
    for _, part in ipairs(parts) do
        TweenService:Create(part, TweenInfo.new(0.1), {Transparency = 1}):Play()
    end
end)

task.delay(0.15, function()
    for _, part in ipairs(parts) do
        part:Destroy()
    end
end)

end

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Coding

audio-system

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

game-systems

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

optimization

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

animation-system

No summary provided by upstream source.

Repository SourceNeeds Review