Particle System Fundamentals
Every property explained โ emission, shape, lifetime, velocity, color over life, size over life, and the Shader setup that makes particles look great.
A Particle System is a component that spawns many small sprites (called particles) and simulates them independently โ each with its own position, velocity, rotation, color, and lifetime. Together they create the illusion of fluids, smoke, fire, magic, and weather.
Unity's built-in particle system is called Shuriken. For advanced VFX, Unity 6 includes the Visual Effect Graph (VFX Graph) โ GPU-based, supports millions of particles.
| System | Max Particles | Best For |
|---|---|---|
| Shuriken (ParticleSystem) | ~10,000 | Mobile, simple FX |
| VFX Graph | Millions | PC/console, cinematic FX |
Main Module
Duration, Looping, Lifetime, Speed, Gravity. The master settings.
Emission
Rate over Time, Rate over Distance, Burst spawning.
Shape
Where particles spawn: Sphere, Cone, Box, Edge, Circle, Mesh.
Velocity over Lifetime
Add velocity curves โ make fire rise, snow drift sideways.
Color over Lifetime
Gradient from spawn to death โ fire goes orangeโredโblack.
Size over Lifetime
Start big, shrink to nothing. Or start small, expand.
Rotation over Lifetime
Spin particles. Great for leaves, debris, embers.
Noise
Turbulence โ makes motion organic. Essential for smoke & magic.
Renderer
Material, sorting, render mode (Billboard, Mesh, Stretched).
Sub Emitters
Particles that spawn other particles on birth/death โ sparks on impact.
Trails
Each particle leaves a ribbon trail. Magic streaks, comet tails.
Lights
Each particle emits a real-time light. Glowing embers, fireflies.
Most glowing FX use Additive blending โ particles add their color to whatever's behind them. Black = invisible, white = full brightness. This is how fire, magic, and glow work.
- Create a Material โ Shader: Universal Render Pipeline/Particles/Unlit.
- Set Surface Type: Transparent, Blending Mode: Additive.
- Assign a particle texture (soft circle, flame shape, star, etc.) to Base Map.
- Set color to white โ color control comes from the Particle System's Color over Lifetime.
- Assign this material in the Particle System's Renderer module.
public class FXController : MonoBehaviour { public ParticleSystem rain; public ParticleSystem fire; void StartRain() { rain.Play(); } void StopRain() { rain.Stop(withChildren: true, stopBehavior: ParticleSystemStopBehavior.StopEmitting); } // Change emission rate at runtime void SetRainIntensity(float rate) { var em = rain.emission; em.rateOverTime = rate; } // Change fire color at runtime void SetFireColor(Color c) { var main = fire.main; main.startColor = c; } // One-shot burst at position void SpawnImpact(Vector3 pos) { ParticleSystem ps = Instantiate(fire, pos, Quaternion.identity); ps.Play(); Destroy(ps.gameObject, ps.main.duration + ps.main.startLifetime.constantMax); } }
๐ง๏ธ Rain Effect
Directional streaks, splash sub-emitters, puddle ripples, and a wet-surface shader โ create a full rain storm system.
- Main Module: Duration: 5, Loop: โ , Start Lifetime: 1.5, Start Speed: 15, Start Size: 0.05, Gravity: 1, Max Particles: 2000.
- Emission: Rate over Time: 400. For a storm, use 600โ800.
- Shape: Box. Width: 20, Height: 1, Depth: 20. Position Y: 8 (above the scene). This rains down over a 20ร20 meter area.
- Renderer: Render Mode: Stretched Billboard, Speed Scale: 0.5, Length Scale: 2. This makes drops look like streaks moving downward.
- Color over Lifetime: Start: rgba(180,220,255,0.9), End: rgba(180,220,255,0). Fades out at the end.
- Sub Emitters: Enable โ Birth: assign a "Splash" particle system (small upward burst of 3โ5 tiny white particles).
- Create a child Particle System called "RainSplash".
- Main: Duration: 0.3, Loop: โ, Start Lifetime: 0.4, Start Speed: 1.5, Start Size: 0.08, Gravity: 2.
- Emission: Burst at time 0 โ Count: 5.
- Shape: Hemisphere, Radius: 0.1. Particles spread outward and upward.
- Color: white โ transparent. Size over Lifetime: big โ small.
- In the parent Rain system โ Sub Emitters โ + โ set Splash here. Condition: Collision.
- Create another child Particle System: "RainRipple".
- Main: Lifetime: 1.2, Start Size: 0.3, Start Speed: 0, Max Particles: 100.
- Shape: Circle, Radius: 0 (emit from center point).
- Size over Lifetime: 0 โ 1 (ring expands outward).
- Color over Lifetime: solid โ fully transparent (ring fades as it expands).
- Renderer: Material using a ring sprite (white circle with hole in center). Render Mode: Billboard.
| Property | Light Rain | Storm | Hurricane |
|---|---|---|---|
| Rate over Time | 150 | 400 | 800 |
| Start Speed | 10 | 15 | 22 |
| Start Lifetime | 2 | 1.5 | 1 |
| Gravity | 0.5 | 1 | 1.5 |
| Max Particles | 500 | 2000 | 4000 |
| Tilt (X rotation) | 0ยฐ | 10ยฐ | 30ยฐ |
โ๏ธ Snow Effect
Soft drifting flakes, turbulence noise for organic movement, accumulation decals, and a blizzard variant.
- Main Module: Duration: 5, Loop: โ , Start Lifetime: min 4, max 8 (random between two constants), Start Speed: min 0.5, max 2, Start Size: min 0.03, max 0.12, Gravity: 0.05, Max Particles: 500.
- Emission: Rate over Time: 60. (Snow is gentler than rain โ fewer, slower particles.)
- Shape: Box, Width: 20, Depth: 20, Height: 0. Position Y: 8. Emit from the Volume (not just the Surface).
- Velocity over Lifetime: X: curve oscillating between -0.5 and 0.5 (drift left/right). Y: -0.5 constant (gentle fall).
- Noise Module: Strength: 0.3, Frequency: 0.5, Scroll Speed: 0.1. This makes flakes drift organically.
- Rotation over Lifetime: Angular Velocity: random between -30 and 30. Flakes spin slowly.
- Size over Lifetime: Stays roughly constant (use a flat curve, slight fade at end).
- Color over Lifetime: Start rgba(255,255,255,0.9), End rgba(255,255,255,0). Fades gently.
- Renderer: Material with a soft white circle sprite. Mode: Billboard.
| Property | Gentle Snow | Blizzard |
|---|---|---|
| Rate over Time | 60 | 300 |
| Start Speed | 0.5 โ 2 | 5 โ 12 |
| Noise Strength | 0.3 | 1.5 |
| Gravity | 0.05 | 0.3 |
| System Tilt X | 5ยฐ | 40ยฐ |
| Velocity X | ยฑ0.5 | ยฑ4 |
For surfaces that accumulate snow over time, use a URP Decal Projector:
- Add โ 3D Object โ Decal Projector to the scene.
- Create a Decal material: Shader Graph โ URP Decal. Set Base Map to a white noise snow texture.
- In C#, animate the Decal Projector's
fadeFactorfrom 0โ1 over 10 seconds to show snow building up.
๐ฅ Fire Effect
Three-layer fire (core, mid, smoke), heat distortion, embers, and a campfire system with dynamic light flickering.
Realistic fire is three stacked particle systems, each representing a different part of the flame:
Layer 1: Core Flame
Bright white-yellow center. Small, fast, hot. Additive blend. 50 particles max.
Layer 2: Mid Flame
Orange-red body. Medium speed, drifts upward. Soft additive. 80 particles.
Layer 3: Smoke
Dark gray, expands, rises. Alpha blend. Slow, large, noisy. 30 particles.
- Main: Lifetime: 0.5โ0.8, Speed: 2โ4, Size: 0.3โ0.6, Max: 50. Simulation Space: World.
- Emission: Rate: 80.
- Shape: Cone, Angle: 10, Radius: 0.1. Tight upward stream.
- Velocity over Lifetime: Y: 1.5 (rises fast). Add slight X wobble: sin curve ยฑ0.3.
- Color over Lifetime:
#ffffff โ #fffba0 โ #ffaa00 โ #ff4400 โ transparent. White hot โ yellow โ orange โ fades. - Size over Lifetime: Ramp up from 0 โ 1 โ 0 (grows then shrinks).
- Noise: Strength: 0.4, Frequency: 2. Makes flame flicker organically.
- Renderer: Additive material, billboard, Sorting Layer: VFX.
- Main: Lifetime: 3โ5, Speed: 0.5โ1, Start Size: 0.4โ0.8, Max: 30. Gravity: -0.1 (floats upward).
- Shape: Cone, Angle: 30, Radius: 0.15. Wider spread than core.
- Color over Lifetime: rgba(80,80,80,0) โ rgba(80,80,80,0.5) โ rgba(0,0,0,0). Appears mid-life, fades out.
- Size over Lifetime: 0.5 โ 2.5. Smoke expands as it rises.
- Velocity over Lifetime: Y: 0.8. Noise Strength: 1.2, Frequency: 0.3. Very turbulent.
- Renderer: Alpha Blend material (not additive โ smoke is opaque, not glowing). Sort in front of environment, behind characters.
- Small, bright orange-white dots. Main: Lifetime: 1.5โ3, Speed: 2โ5, Size: 0.04, Max: 50.
- Emission: Burst mode โ spawn 2โ4 every 0.2 seconds.
- Velocity over Lifetime: Y: 0.5โ2, X: random ยฑ1. Embers fly upward and sideways.
- Rotation over Lifetime: ยฑ180 deg/sec โ they spin.
- Color: white-orange โ transparent. Additive blend.
- Lights module: Enable โ Ratio: 0.3. 30% of embers emit a real point light! Max Lights: 4. Intensity: 0.5, Range: 0.5. This creates real flickering light from embers.
public class FireLightFlicker : MonoBehaviour { public Light fireLight; public float baseIntensity = 3f; public float flickerAmount = 1.5f; public float flickerSpeed = 12f; private float noise; void Update() { noise = Mathf.PerlinNoise(Time.time * flickerSpeed, 0); fireLight.intensity = baseIntensity + (noise - 0.5f) * flickerAmount; // Optional: slight color shift hotโcool fireLight.color = Color.Lerp( new Color(1f, 0.5f, 0.1f), new Color(1f, 0.8f, 0.3f), noise); } }
๐ง Water & Bubbles
Drips, splashes, water jets, rising bubbles, and underwater ambient particles.
- Main: Lifetime: 0.8, Speed: 4, Start Size: 0.08, Gravity: 2, Max: 20.
- Emission: Burst โ 1 particle every 0.5 seconds (drip drip drip).
- Shape: Point (single emission point).
- Velocity: Y: -5 (falls down), no X deviation for clean drip.
- Color: rgba(100,180,255,0.9) โ transparent. Size over Lifetime: constant then rapid shrink at end (splat).
- Sub Emitters โ Collision: tiny splash burst (5 particles in cone, upward, size 0.04, lifetime 0.3).
- Main: Lifetime: 2โ4, Speed: 0.5โ1.5, Start Size: 0.05โ0.2 (random), Gravity: -0.5 (negative = floats up), Max: 80.
- Emission: Rate: 15.
- Shape: Box (represents underwater floor area). Width/Depth: 5, Height: 0.
- Velocity over Lifetime: Y: 1. Slight X wobble (sin oscillation ยฑ0.2).
- Color: rgba(150,220,255,0.6) โ rgba(200,240,255,0.1). Semi-transparent, fades at top.
- Size over Lifetime: small โ grows slightly โ pops (shrinks to 0 at end).
- Renderer: Material with a circle sprite, set to Transparent blend (not additive โ bubbles aren't glowing).
- Main: Lifetime: 1โ2, Speed: 8โ12, Gravity: 2, Start Size: 0.1โ0.15, Max: 200.
- Emission: Rate: 150.
- Shape: Cone, Angle: 5โ15 (tight stream), Radius: 0.02.
- Velocity over Lifetime: Limit over Lifetime: 0.5 (drag โ slows particles naturally like water).
- Collision Module: Enable โ Type: World. Dampen: 0.2, Bounce: 0.1. Particles collide with the ground/pool surface.
- Sub Emitters โ Collision: splash burst.
๐ Ocean & Water Surface
Ocean uses a combination of a shader-animated mesh + particle foam/spray โ not a pure particle system.
Real game oceans combine three systems:
1. Wave Mesh Shader
A subdivided plane animated by a Shader Graph vertex displacement using sine waves.
2. Foam Particles
White particle sprites along wave crests and shorelines.
3. Spray Particles
Fine mist particles above wave crests, additive blend.
- Create a Shader Graph: URP Lit. Set Surface: Transparent.
- In Vertex stage: add a Position node (object space). Feed the Y into a Sine node driven by
Time ร waveSpeed + X ร waveFrequency. Output to Vertex Position Y. This makes the mesh ripple. - For depth color: sample screen-space depth, blend between shallow color (light cyan) and deep color (dark blue) based on depth value.
- Add Normal Map from a tiling water normal texture, scrolling over time (two UV sets scrolling in opposite directions for complex ripple).
- Set Smoothness: 0.95. Specular: high. This gives the glossy water look.
- Foam: Large, white, soft-edged circle sprites. Lifetime: 2โ4, Speed: 0, Size: 0.5โ1.5. Shape: Edge along shoreline or wave crest. Alpha blend, not additive. Slow fade-in and fade-out.
- Spray/Mist: Tiny white dots. Lifetime: 0.5โ1, Speed: 1โ3 (upward + outward from wave). Additive blend. Size: 0.03โ0.08. Noise Strength: 1. Creates fine water mist that catches light beautifully.
๐ด Fireballs & Projectiles
A moving fireball with trailing fire, a glowing core, and an impact explosion โ all driven from a prefab that travels through the scene.
- Main: Lifetime: 0.6, Speed: 0, Start Size: 0.4โ0.8, Max: 100. Simulation Space: World (critical โ trail stays behind in world space as fireball moves).
- Emission: Rate: 60.
- Shape: Sphere, Radius: 0.1. Emits in all directions from the fireball center.
- Velocity over Lifetime: Orbital mode โ slight spiral for swirling fire trail.
- Color over Lifetime:
white โ yellow โ orange โ red โ transparent. - Size over Lifetime: 1 โ 0. Shrinks as the trail ages (particles get smaller as they fall behind).
- Noise: Strength: 0.8, Frequency: 3. Organic swirling motion.
public class Fireball : MonoBehaviour { public float speed = 12f; public ParticleSystem explosion; public float damage = 40f; public float blastRadius = 3f; void Update() { transform.Translate(Vector3.forward * speed * Time.deltaTime); } void OnTriggerEnter(Collider other) { if (other.CompareTag("Player") || other.CompareTag("Environment")) { Explode(); } } void Explode() { // Detach explosion, disable travel var vfx = Instantiate(explosion, transform.position, Quaternion.identity); vfx.Play(); Destroy(vfx.gameObject, 3f); // Area damage Collider[] hits = Physics.OverlapSphere(transform.position, blastRadius); foreach (var h in hits) { var hp = h.GetComponent<Health>(); if (hp != null) hp.TakeDamage(damage); } Destroy(gameObject); } }
- Shape: Sphere, Radius: 0.3. Emits in all directions.
- Emission: Burst โ Count: 60, Time: 0. One massive simultaneous burst.
- Main: Lifetime: 0.6โ1.2, Speed: 5โ15 (fast outward), Size: 0.3โ0.8, Gravity: 0.5.
- Color: white โ orange โ dark red โ transparent (fast fade).
- Add a separate Shockwave: a single disc particle, starts small, expands quickly, flat, additive white. Size over Lifetime: 0 โ 3 over 0.3 seconds.
- Add Debris sub-system: dark gray chunks, gravity 2, bounce collision, slow rotation. Stays on the ground after explosion.
๐ฎ Magic & Spells
Portal vortex, floating rune particles, energy beams, magic circle, and a fully scripted spell casting system.
- Main: Lifetime: 1โ2, Speed: 0.5โ2, Start Size: 0.05โ0.15, Max: 150.
- Emission: Rate: 40. Also add 3 Bursts spaced 0.5s apart, Count: 8.
- Shape: Sphere, Radius: 0.5. Particles spawn in a sphere around the caster.
- Velocity over Lifetime: Orbital โ X: 2, Y: 2. Particles orbit the center like electrons around an atom.
- Color: random from gradient: purple, cyan, white, gold. Use "Random Between Two Colors" mode for magical variety.
- Noise: Strength: 0.5, Frequency: 1.5. Subtle shimmer movement.
- Trails Module: Enable โ Lifetime: 0.3, Width: 0.02. Each sparkle leaves a short glowing trail.
- Renderer: Star or cross sprite, Additive blend.
- Main: Lifetime: 2, Speed: 1โ3, Gravity: 0, Max: 300.
- Shape: Circle, Radius: 2, Emit from Edge. Particles start at the outer edge.
- Velocity over Lifetime: Orbital โ spin particles. Also add Linear Y: slight pull toward center.
- Color: outer starts dark, inner goes bright cyan/purple. Over Lifetime: dark purple โ bright cyan โ white.
- Size over Lifetime: starts large, shrinks to 0 as they reach center (sucked in).
- Rotation over Lifetime: 180 deg/sec. Particles spin as they spiral inward.
- Add a second system with larger, slower particles (ring wisps) for layered depth.
A beam is a LineRenderer for the core, plus particle systems for charge-up and impact.
public class MagicBeam : MonoBehaviour { public LineRenderer beam; public Transform target; public ParticleSystem impactVFX; public float widthPulse = 0.05f; void Update() { // Draw beam from caster to target beam.SetPosition(0, transform.position); beam.SetPosition(1, target.position); // Pulse the width for energy feel float w = widthPulse + Mathf.Sin(Time.time * 20f) * 0.01f; beam.startWidth = w; beam.endWidth = w * 0.5f; // Move impact VFX to beam endpoint impactVFX.transform.position = target.position; } }
Set the LineRenderer material to Additive + a beam texture (white gradient from center to edge). Add a blue/purple point light to the target impact VFX.
- Create a flat quad at Y=0.01 (just above ground). Material: Additive, with a magic circle rune texture. Animate rotation via script.
- Add a particle system on the circle edge (Shape: Circle, Radius: 1.5, Emit from Edge). Slow-rising magical wisps.
- Add rising rune sprites (Texture Sheet Animation module, multiple rune frames, random start frame). Particles float up and fade.
โจ Glow & Bloom
URP Bloom post-processing, emissive materials, glowing particles, HDR colors, and the full pipeline for making things luminous.
Glow is not a particle effect โ it's a post-processing effect called Bloom. Here's how the pipeline works:
- Objects use HDR (High Dynamic Range) colors โ values above 1.0 in the color picker. Normal colors max at 1.0; HDR goes to 3.0, 5.0, 10.0+.
- URP renders the scene normally.
- Bloom post-process reads all pixels brighter than a threshold and bleeds their light outward โ creating the glow halo.
- Result: anything emitting HDR light glows. Regular colored objects don't.
- Project Settings โ Graphics โ Scriptable Render Pipeline Settings โ your URP asset. Ensure HDR: On and Post Processing: On.
- In Scene: Add โ Volume โ Global Volume. Add a new Profile.
- Add Override โ Bloom. Set Threshold: 1.0 (glow anything above this), Intensity: 0.5โ1.5, Scatter: 0.7.
- Also add Color Adjustments (slight saturation +10) and Vignette for atmosphere.
- On Camera: ensure Post Processing: โ .
Emissive Material:
- Material โ URP/Lit โ enable Emission.
- Set Emission Color using the HDR color picker โ drag intensity above 1.0.
- This material now glows wherever Bloom is active.
Glowing Particle:
- Additive particle material automatically glows with Bloom enabled.
- Set Start Color to HDR white (intensity 3.0+).
- White additive particles become intense bloom halos.
- Main: Lifetime: 4โ8, Speed: 0.2โ0.8, Size: 0.06โ0.1, Max: 30, Simulation Space: World.
- Shape: Box covering scene area.
- Velocity over Lifetime: Random between (-1,-0.5,-1) and (1,0.5,1). Gentle drifting.
- Noise: Strength: 0.5, Frequency: 0.3, Scroll Speed: 0.1. Organic flight pattern.
- Color over Lifetime: starts transparent, peaks at HDR yellow-green (R:0.6, G:1.0, B:0.2, A:1.0, Intensity: 2.5), fades out. Pulsing blink effect.
- Lights Module: Ratio: 0.5. Half of fireflies emit a real point light (range 0.8, intensity 0.6, color warm green).
๐ก Dynamic Lights
Particle-driven lights, animated light patterns, color-shifting dramatic effects, and the Lights module deep dive.
The Lights module in a Particle System lets each particle emit a real-time Unity Light. Used carefully, this creates incredible interactive lighting from effects.
| Property | Description |
|---|---|
| Light | Assign a Point Light prefab here |
| Ratio | 0.0โ1.0 โ what fraction of particles get a light. Keep below 0.3 for performance. |
| Random Distribution | Which particles get lights (random vs all) |
| Use Particle Color | Light color matches particle color (great for fire!) |
| Size Affects Range | Bigger particles = bigger light radius |
| Alpha Affects Intensity | Fading particles dim their lights (very realistic) |
| Range Multiplier | Scale the light radius |
| Intensity Multiplier | Scale brightness |
| Maximum Lights | Hard cap โ never exceed 8 for mobile |
- Create the flame particle system (see Fire module). Layer: Core, Mid, Embers.
- On the Embers system โ Lights Module โ assign a warm orange Point Light prefab. Ratio: 0.2. Max: 3.
- On a parent GameObject, attach FireLightFlicker.cs. Perlin noise drives intensity fluctuation.
- Result: 2โ3 dynamic lights from embers, plus the base flicker, creates convincingly real torch lighting.
public class LightAnimator : MonoBehaviour { public Light lt; public enum Mode { Siren, Alarm, Flicker, Pulse } public Mode mode; public float speed = 3f; void Update() { float t = Time.time * speed; switch (mode) { case Mode.Siren: lt.color = Mathf.Sin(t) > 0 ? Color.red : Color.blue; lt.intensity = 5f; break; case Mode.Alarm: lt.intensity = Mathf.PingPong(t * 2, 6f); break; case Mode.Flicker: lt.intensity = Mathf.PerlinNoise(t, 0) * 5f; break; case Mode.Pulse: lt.intensity = (1 + Mathf.Sin(t)) * 2.5f; break; } } }
โก Lightning & Electricity
Procedural lightning bolts, electric arc particles, charged-up VFX, and a Tesla coil effect.
public class LightningBolt : MonoBehaviour { public LineRenderer lr; public Transform start, end; public int segments = 12; public float jaggedness = 0.4f; public float refreshRate = 0.03f; private float timer; void Update() { timer -= Time.deltaTime; if (timer > 0) return; timer = refreshRate; GenerateBolt(start.position, end.position); } void GenerateBolt(Vector3 a, Vector3 b) { lr.positionCount = segments; for (int i = 0; i < segments; i++) { float t = (float)i / (segments - 1); Vector3 mid = Vector3.Lerp(a, b, t); Vector3 perp = Vector3.Cross((b - a).normalized, Vector3.forward); mid += perp * Random.Range(-jaggedness, jaggedness); mid += Vector3.up * Random.Range(-jaggedness, jaggedness); lr.SetPosition(i, mid); } } }
Set the LineRenderer material to Additive with a bright blue-white gradient. Set Width: 0.02. The bolt regenerates every 30ms to create the electric flicker.
- Main: Lifetime: 0.2โ0.5, Speed: 3โ8, Start Size: 0.03โ0.06, Gravity: 1, Max: 80.
- Emission: Rate: 0. Bursts only โ 10โ20 sparks every 0.05 seconds.
- Shape: Point or tiny Sphere (radius 0.05).
- Velocity: Random outward in all directions. Speed: 5โ12.
- Color: white โ blue-white โ transparent. Very fast fade.
- Rotation: 360 deg/sec random. Sparks tumble.
- Renderer: Stretched Billboard, Speed Scale: 0.8. Sparks leave bright streaks.
๐ฅ Explosions & Impact Effects
Full explosion prefab system โ shockwave, flash, debris, smoke, fire aftermath, and screen shake integration.
1. Flash
Instant white sphere. Lifetime: 0.1s. Single burst of 1 giant particle. Size: 5. Additive. The eye-searing first frame.
2. Fireball
Expanding orange sphere. Lifetime: 0.6s. Size: 0โ3 quickly. Additive fire material.
3. Shockwave
Ring disc expanding outward. Single flat particle, scale 0โ6 in 0.2s. Rim-lit additive ring texture.
4. Smoke
Large billowing gray clouds. Lifetime: 3โ6s. Size: 2โ8. Alpha blend. Slow turbulent rise.
5. Debris
Dark chunks flying outward. Gravity, bounce, real collision. Stays on ground permanently.
6. Sparks
Fast bright orange lines. Stretched billboard, Speed Scale 1.5. Short lifetime (0.3s). Sizzle out quickly.
public class CameraShake : MonoBehaviour { public static CameraShake I; private float trauma; private float seed; public float maxAngle = 10f; public float maxOffset = 0.3f; public float traumaDecay = 1.5f; void Awake() => I = this; public void AddTrauma(float amount) => trauma = Mathf.Clamp01(trauma + amount); void Update() { if (trauma <= 0f) { trauma = 0; return; } float shake = trauma * trauma; // quadratic = natural falloff seed += Time.deltaTime; transform.localRotation = Quaternion.Euler( maxAngle * shake * Mathf.PerlinNoise(seed, 0), maxAngle * shake * Mathf.PerlinNoise(seed, 1), maxAngle * shake * Mathf.PerlinNoise(seed, 2)); trauma -= traumaDecay * Time.deltaTime; } } // Usage anywhere โ e.g. in explosion script: // CameraShake.I.AddTrauma(0.6f);
๐ฑ Mobile FX Optimization
Hit 60fps with great-looking effects โ GPU budgets, LOD particles, culling, pooling, and the mobile FX checklist.
| Effect | Safe Mobile Count | Max Count |
|---|---|---|
| Rain | 500 | 1500 |
| Snow | 150 | 400 |
| Fire (campfire) | 80 | 200 |
| Magic sparkles | 60 | 150 |
| Explosion (one-shot) | 80 | 200 |
| Simultaneous explosions | 2 max | 4 max |
| Particle lights | 4 max | 8 absolute max |
| Total scene particles | <2000 | 5000 risk |
public class VFXPool : MonoBehaviour { public static VFXPool I; [System.Serializable] public class VFXEntry { public string id; public ParticleSystem prefab; public int poolSize = 5; } public VFXEntry[] effects; private Dictionary<string, Queue<ParticleSystem>> pools; void Awake() { I = this; pools = new Dictionary<string, Queue<ParticleSystem>>(); foreach (var e in effects) { var q = new Queue<ParticleSystem>(); for (int i = 0; i < e.poolSize; i++) { var ps = Instantiate(e.prefab); ps.gameObject.SetActive(false); q.Enqueue(ps); } pools[e.id] = q; } } public void Play(string id, Vector3 pos) { if (!pools.ContainsKey(id) || pools[id].Count == 0) return; var ps = pools[id].Dequeue(); ps.transform.position = pos; ps.gameObject.SetActive(true); ps.Play(); StartCoroutine(Return(id, ps)); } IEnumerator Return(string id, ParticleSystem ps) { yield return new WaitForSeconds(ps.main.duration + 0.5f); ps.Stop(true, ParticleSystemStopBehavior.StopEmittingAndClear); ps.gameObject.SetActive(false); pools[id].Enqueue(ps); } } // Usage: VFXPool.I.Play("Explosion", hitPoint);
| Check | Why It Matters |
|---|---|
| โ Max Particles set on every system | Prevents runaway spawn on slow devices |
| โ Culling Mode: Pause And Catch Up | Stops off-screen particles from simulating |
| โ Ring Buffer mode on looping FX | Reuses particle slots instead of allocating |
| โ Texture atlases for particle sprites | One draw call for all particle types |
| โ Particle Lights: Max โค 4 per system | Real-time lights are expensive on mobile |
| โ Bloom Intensity โค 1.5 | High bloom = GPU bandwidth spike |
| โ No PolygonCollider on particle collision | Use simplified colliders for particle physics |
| โ All one-shot FX pooled | Destroy() causes GC spikes = frame drops |
| โ Profiler tested on real device | PC performance โ phone performance |
Build a Complete Death Road Weather System
- Rain (400 particles/sec) with splash sub-emitter
- Distant lightning (LineRenderer bolt + flash + thunder sound)
- Campfire with 3 layers + flickering point light + embers
- Magic healing effect on player (orbital sparkles + bloom + circle ground projection)
- Explosion on enemy death (flash + shockwave + debris + smoke + screen shake)
- All FX pooled, all particle counts within mobile budget
- Bloom post-processing enabled and tuned