🎯

vfx-effects

🎯Skill

from taozhuo/game-dev-skills

VibeIndex|
What it does

Generates dynamic visual effects like particle systems, camera shakes, and impact animations for enhancing game experiences in Roblox.

vfx-effects

Installation

Install skill:
npx skills add https://github.com/taozhuo/game-dev-skills --skill vfx-effects
2
AddedJan 27, 2026

Skill Details

SKILL.md

Implements visual effects including particle systems, camera effects, lighting, mesh effects, and UI animations. Use when creating combat VFX, environmental effects, feedback systems, or any visual polish.

Overview

# Roblox Visual Effects (VFX)

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

Particle Effects

Anime Hit VFX

```lua

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

```lua

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

```lua

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

```lua

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)

```lua

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

```lua

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

```lua

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

```lua

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

```lua

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

```lua

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

```lua

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

```lua

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

```lua

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

```lua

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

```

More from this repository10

🎯
audio-system🎯Skill

Manages audio systems with advanced sound pooling, priority management, and performance optimization for immersive game sound experiences.

🎯
optimization🎯Skill

optimization skill from taozhuo/game-dev-skills

🎯
animation-system🎯Skill

animation-system skill from taozhuo/game-dev-skills

🎯
game-systems🎯Skill

Implements robust game systems like inventory, shops, trading, and progression mechanics for Roblox RPGs with secure, stackable item management.

🎯
gemini-image-prompting🎯Skill

Generates conceptual game art images using Gemini AI, providing precise style-specific prompts for character, environment, and UI design across various game aesthetics.

🎯
combat-system🎯Skill

Enables comprehensive combat mechanics with advanced hitbox detection, damage calculation, and hit validation for creating dynamic player-vs-player and player-vs-NPC combat interactions.

🎯
security-anticheat🎯Skill

security-anticheat skill from taozhuo/game-dev-skills

🎯
roblox-api-patterns🎯Skill

Provides expert guidance on navigating Roblox-specific API behaviors, performance optimizations, and common coding pitfalls in Lua scripting.

🎯
data-persistence🎯Skill

Manages reliable Roblox data persistence by implementing robust data loading, saving, caching, and error handling for player progress and game state.

🎯
procedural-generation🎯Skill

Generates procedurally randomized content like terrain, dungeons, and cities using advanced noise algorithms and algorithmic techniques.