vfx-effects
π―Skillfrom taozhuo/game-dev-skills
Generates dynamic visual effects like particle systems, camera shakes, and impact animations for enhancing game experiences in Roblox.
Installation
npx skills add https://github.com/taozhuo/game-dev-skills --skill vfx-effectsSkill Details
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
Manages audio systems with advanced sound pooling, priority management, and performance optimization for immersive game sound experiences.
optimization skill from taozhuo/game-dev-skills
animation-system skill from taozhuo/game-dev-skills
Implements robust game systems like inventory, shops, trading, and progression mechanics for Roblox RPGs with secure, stackable item management.
Generates conceptual game art images using Gemini AI, providing precise style-specific prompts for character, environment, and UI design across various game aesthetics.
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 from taozhuo/game-dev-skills
Provides expert guidance on navigating Roblox-specific API behaviors, performance optimizations, and common coding pitfalls in Lua scripting.
Manages reliable Roblox data persistence by implementing robust data loading, saving, caching, and error handling for player progress and game state.
Generates procedurally randomized content like terrain, dungeons, and cities using advanced noise algorithms and algorithmic techniques.