---
title: "VFX"
slug: /workflows/vfx/
markdown: /workflows/vfx.md
section: art-audio-animation
tier: 2
summary: "General VFX rules for any Unity project: layered effects, particles, shaders, warm-up, cost and accessibility."
sources: ['earlier status-effect page (general rules only)', 'vfx-allin1.md (layered recipe)', 'animation.md', 'rendering-urp.md', 'perf-memory.md']
canonical: https://unityworkflowlibrary.dev/workflows/vfx/
read_first: /read-first.md
---

> Read first, on every prompt: [non-destructive rules](/read-first.md).

# VFX

> General VFX rules for any Unity project: layered effects, particles, shaders, warm-up, cost and accessibility.

Vendor-neutral guidance for building effects in any Unity project, in URP or HDRP, with Shader Graph, the built-in Particle System or VFX Graph. Use it when you add the first effect to a project and again before you ship. Rules that were learned on a specific page stay there with their measurements and provenance; this page gives the short version and links to the full rule.

## Build an effect: the layered recipe

- **EFFECT-IS-A-STACK-OF-CHEAP-LAYERS — build each effect from a few cheap layers, not one rich one.**
  - Rule: nested soft additive glows, a shaped body (a flipbook, or a scrolled and eroded texture), accents (sparks, rings, spikes) and, only where needed, a little alpha-blended smoke. A bolt can be three nested stretched additive quads; a fire can be two glows, a flame and sparks.
  - Why: a few cheap layers read richer than one expensive one, and each can be tuned or cut on its own.
  - Check: every layer has a job you can name, and removing any layer visibly loses something.
- **BLOOM-BRIGHTNESS-IS-STACKED-ADDITIVE — reach the bloom threshold by stacking LDR additive layers, not one HDR colour.**
  - Rule: several One/One additive layers that sum past the bloom threshold give more control and cost less than one quad with an HDR multiplier. Use the default render queues; additive layers need no sorting, so the blend mode does the layering. Keep alpha blending for smoke and soft rings.
  - Check: the effect reads the same with bloom on and off, apart from the glow.
- **MOTION-SELLS-THE-LOOK — timing and texture motion matter more than texture detail.**
  - Rule: hard `smoothstep` alpha edges; a two- or three-tone colour ramp over the life of the effect; short flash pops staggered in small beats; near-instant scale-in; shape and erosion textures scrolling at different speeds; mesh layers (cones, rings, planes) with offset pivots for whooshes that move outward.
  - Check: play the effect at quarter speed; each beat is visible and the layers do not move in lockstep.
- **EXPLOSIONS-POP-THEN-ERODE — never a linear scale-up.**
  - Rule: a violent front-loaded pop (an ease-out curve), then the layers erode away through a noise dissolve with a glowing burn edge; fade alpha only in the last beat.
  - Why: one mesh with a linear scale or fade reads as dated, whatever the texture quality.
  - Check: the silhouette changes over the burst instead of only growing.
- **SOLID-FORM-PLUS-ENERGY — a physical core is one mesh wrapped in additive shells.**
  - Rule: when an effect must read as an object (a crystal bolt, a rune disc), use one low-poly mesh as the core and wrap it with one to three additive energy layers. A bare lit mesh at gameplay distance reads as a prop, not magic. Pivot at the flight centre.
  - Check: at the gameplay camera the effect reads as energy, not as a dropped prop.
- **PICK-THE-PATH-BY-WHAT-COST-SCALES-WITH — layered meshes for many actors, pooled particles for events.**
  - Rule: effects that fly with many actors (projectiles, trails, auras) are mesh layers drawn instanced. Particle systems and VFX Graph are for event-rate effects (impacts, casts, heals) from a capped pool. Never put a particle system on every unit of a high-count actor.
  - Check: doubling the unit count does not double the number of live particle systems.

## Particle systems

- **ONE-SHOTS-FIRE-ON-AN-EDGE — bursts fire once, on a state change, never from a per-frame condition.**
  - Rule: emit from the transition (a value crossing a threshold, a flag going true, a counter incrementing) with `ParticleSystem.Emit(count)` or a Burst entry, and use Sub Emitters for secondary sparks instead of spawning new systems from code. A per-frame follower only moves the system; it never calls `Clear` and `Play` every frame.
  - Why: a burst fired from an `Update` condition restarts every frame and turns into a fountain, or pins particles at age 0 where size-over-lifetime curves make them invisible.
  - Check: holding the trigger value constant produces no new bursts. Full rules: ONE-SHOTS-ARE-EDGE-TRIGGERS and PARTICLE-SHOW-IS-EDGE-TRIGGERED on the [Animation (Mecanim)](/workflows/animation/) page.
- **PARTICLE-SYSTEMS-ARE-POOLED — attached effects come from a pool and return to it.**
  - Rule: pre-create effect prefabs, attach on use, and on release call `Stop(true, ParticleSystemStopBehavior.StopEmittingAndClear)` (or let the effect finish) before returning it. If the pool scales the root, every descendant system uses `scalingMode = Hierarchy`, and scale is reset on return.
  - Check: using and releasing an effect 100 times creates no new GameObjects after warm-up. Full rule: POOLED-PARTICLE-SCALE-INCLUDES-DESCENDANTS on the [Animation](/workflows/animation/) page.
- **SUB-EMITTERS-AND-MODULES-HAVE-TRAPS — author sub-emitters and curves so they cannot misfire.**
  - Rule: sub-emitters have Play On Awake off; enabled velocity-over-lifetime axes share one curve mode; a test that calls `Simulate` resumes playback before it judges `IsAlive`.
  - Check: Play mode shows no velocity-mode errors and no sub-emitter firing on its own. Full rules: SUB-EMITTER-PLAYS-ON-ITS-OWN, PARTICLE-VELOCITY-AXES-SHARE-CURVE-MODE and PARTICLE-SIMULATE-PAUSES-THE-CLOCK on the [Animation](/workflows/animation/) page.

## Shaders and materials

- **SHADER-GRAPH-TARGETS-MATCH-THE-PIPELINE — a graph without your pipeline's target draws nothing, silently.**
  - Rule: every effect graph lists the target of the pipeline you ship (URP or HDRP); converted vendor graphs are checked too.
  - Check: open the graph's Graph Settings and confirm the target. Full rule: SHADERGRAPH-TARGET-MUST-MATCH-THE-PIPELINE on the [Rendering & URP](/workflows/rendering-urp/) page.
- **ADDITIVE-MEANS-THE-BLEND-MODE — check the blend state, not the material name.**
  - Rule: a glow material named "Additive" can still be alpha-blended and draw black squares; read its blend mode. A layered hit core (flare, glow, ring, sparks) uses additive materials, because stacked alpha-blended HDR white saturates to an opaque disc.
  - Check: no glow quad shows a dark or opaque square in Play. Full rules: ADDITIVE-NAME-IS-NOT-ADDITIVE-BLEND and LAYERED-HIT-CORE-IS-ADDITIVE on the [Rendering](/workflows/rendering-urp/) page.
- **SOFT-PARTICLES-NEED-DEPTH — soft particles render blank without the camera depth texture.**
  - Rule: either enable the depth texture on every renderer that draws them, or strip the soft-particle keyword on tiers that turn depth off. Depth and scene-colour features (soft particles, depth glow, screen distortion) also cost mobile bandwidth, so keep them off high-density effects.
  - Check: test on the mobile renderer asset, not only in the Scene view. Full rule: SOFT-PARTICLES-NEED-THE-DEPTH-TEXTURE on the [Rendering](/workflows/rendering-urp/) page.
- **DECALS-PROJECT-INTO-THE-SURFACE — impact decals point into the hit and are parented to what they mark.**
  - Rule: point the projector's +Z into the surface; parent the mark to the object it sits on.
  - Check: live shots from several angles show no floating or missing marks. Full rule: DECAL-FACES-INTO-THE-HIT on the [Rendering](/workflows/rendering-urp/) page.
- **ONE-PARAMETER-DRIVES-THE-EFFECT — a material-driven effect is one 0..1 float, and gameplay writes only that.**
  - Rule: derive mask thresholds, emission, pulse speed and dissolve edge from one float (for example `_Amount`). For steps the player must notice, shape the float with a curve or thresholds instead of a slow fade.
  - Why: one value is easy to animate, save, replicate, reset and test; separate flags drift out of sync and leave half-applied looks.
  - Check: scrub the value from 0 to 1; every stage appears in order, and 0 is exactly the clean look.
- **PER-INSTANCE-VALUES-NEVER-NEW-MATERIALS (HARD) — set per-renderer values without creating materials at runtime.**
  - Rule: cache `Shader.PropertyToID` once. Use one reused `MaterialPropertyBlock`, a GPU-instanced property, Entities Graphics per-instance overrides (`[MaterialProperty]`), or a material instance created once at spawn and destroyed with the object. Never touch `renderer.material` in a per-frame path: each first access clones the material.
  - Why: clones leak and break batching. In URP and HDRP a property block also drops the renderer out of the SRP Batcher, so for crowds prefer instanced properties or a few shared materials.
  - Check: the Memory Profiler shows the same material count before and after a long fight.
- **VALUES-NOT-KEYWORDS — stages and intensities change floats, not shader keywords.**
  - Rule: use a keyword only for a genuinely different feature, and prefer `shader_feature_local`. A keyword enabled at runtime that no build material uses has no variant in the player. Remember the player strips anything it cannot prove is used.
  - Check: the build's variant report does not grow when you add a stage. Full rule: SHADER-VARIANTS-STRIP-IN-THE-PLAYER on the [Rendering](/workflows/rendering-urp/) page.

## Warm-up and first play

- **VFX-GRAPH-WARMS-BY-BEING-PLAYED (HARD) — play each graph once during loading.**
  - Rule: the first enable of a VFX Graph compiles its shaders and builds its buffers on that frame; no preload list covers it. Play it once, off-screen, while loading.
  - Check: the first in-game play has no hitch. Full rule with measurements on the [Rendering](/workflows/rendering-urp/) page; for other shaders see GPU-WARMUP-NEEDS-A-REAL-DRAW on the [Performance & memory](/workflows/perf-memory/) page.
- **VFX-GRAPH-ONLY-WHERE-COMPUTE-IS-SAFE — choose VFX Graph or the Particle System by platform.**
  - Rule: VFX Graph needs compute shaders; use it for dense effects on PC and console, and the built-in Particle System on low-end mobile and WebGL. Particle shaders with procedural instancing can skip their draws on some Vulkan devices.
  - Check: the effect draws on the lowest target device. See PROCEDURAL-PARTICLE-INSTANCING-SKIPS-ON-VULKAN on the [Rendering](/workflows/rendering-urp/) page.
- **VENDOR-DURATION-IS-A-LIFETIME — read a vendor graph's exposed curves before driving it from code.**
  - Rule: to hold a one-shot graph, re-play it before it ends instead of raising its duration.
  - Check: the effect clears on release. Full rule: VENDOR-VFX-DURATION-IS-A-LIFETIME on the [Rendering](/workflows/rendering-urp/) page.

## Readability: hit cores, flashes and streaks

- **JUDGE-EFFECTS-AT-GAMEPLAY-DISTANCE — accept an effect from the game camera, not zoomed in.**
  - Rule: glows narrower than the core, no full impact prefab replayed at every hop of a chained streak or beam, and a final look check at the real camera distance.
  - Check: a capture from the gameplay camera reads as the effect, not as one white blob. Full rule on the [Rendering](/workflows/rendering-urp/) page.
- **FLASHES-ARE-CAPPED-TOGETHER — tint plus emission, and flash plus light, are budgeted as a sum.**
  - Rule: cap a hit flash's tint and emission together so the unit never turns into a white silhouette under bloom; size a flash particle from the range of the light it sits on.
  - Check: struck units stay readable with bloom on. Full rules: HIT-FLASH-CAPS-TINT-PLUS-EMISSION and FLASH-AND-LIGHT-ADD-UP on the [Rendering](/workflows/rendering-urp/) page.
- **READS-WITHOUT-HUE — every effect state is readable with colour removed.**
  - Rule: pair each hue with a non-colour cue: shape, pattern or motion. Give each effect type one hue family and reuse it in the world, the particles and the UI icon.
  - Check: view effects through a greyscale or colour-blindness filter; each stays distinct.

## Lifecycle and networking

- **ONE-OWNER-FOR-APPLY-TICK-CLEAR (HARD) — one component owns an effect from start to clear.**
  - Rule: the owner sets the start value, attaches pooled effects, writes the shader parameter only when it changes, and on clear sets the value to 0 and returns every effect it turned on.
  - Check: ending the effect removes every visual in the same frame.
- **CLEANUP-ON-EVERY-EXIT-PATH (HARD) — death, despawn, scene unload and pool return all run the clear.**
  - Rule: call the same clear from every exit path (`OnDisable` is a safe catch-all) and reset the parameter on the property block or material.
  - Why: pooled objects keep their property block values, so a fresh spawn can walk out of the pool mid-effect.
  - Check: apply an effect, kill the object, and spawn until the pool reuses it; it is clean.
- **REPLICATE-THE-VALUE-NOT-THE-VISUALS — the network carries the parameter; clients derive the effect.**
  - Rule: replicate only the authoritative value, quantized, and let each client set its own shader, particles and audio. Detect start and end as state transitions on each client.
  - Check: a late joiner shows the same state without a replay of onset effects.

## Cost and accessibility

- **ZERO-ALLOCATION-BY-DEFAULT applies to effects too.**
  - Rule: cached property IDs, a reused `MaterialPropertyBlock`, no LINQ or closures in effect ticks, pooled systems (see ZERO-ALLOCATION-BY-DEFAULT on the [C# style](/workflows/csharp-style/) page).
  - Check: Profiler GC Alloc is 0 B on frames with many effects running.
- **OVERDRAW-IS-THE-REAL-COST — stacked transparent layers cost fill rate.**
  - Rule: keep alpha smoke few and large, keep particle sizes in check near the camera, cap simultaneous puffs, and use alpha clipping where you can.
  - Check: Scene view Overdraw mode or the Rendering Debugger with the camera pushed into the densest effect.
- **PARTICLE-CAPS-ARE-MEASURED-ON-DEVICE — caps come from a real draw on the lowest target device.**
  - Rule: `Max Particles` is a ceiling and CPU render time is not GPU cost; set caps from GPU frame time with the effect's pixels on screen. Mobile defaults first, with a raised ceiling for PC from the same pools.
  - Check: the device capture is recorded next to the cap. Full rule: PARTICLE-COST-NEEDS-A-REAL-DRAW on the [Performance & memory](/workflows/perf-memory/) page.
- **NO-RAPID-FULL-SCREEN-FLASHES (HARD) — no large-area flash faster than three per second.**
  - Rule: keep full-screen or large-area flashes below three per second (WCAG 2.3.1), avoid saturated red flashes, prefer a slow edge vignette, and offer a screen-effects intensity setting. Never put critical information only in a screen effect.
  - Check: record the worst case and count flashes per second.
- **EFFECT-IS-PROVEN-BY-ITS-OUTPUT — a settings readback is not proof an effect renders.**
  - Check: look at the pixels or the pass counters. Full rule on the [Rendering](/workflows/rendering-urp/) page.

## Related rules elsewhere

Two locked, field-tested rules live on general pages and apply to every effect:

- **ONE-SHOTS-ARE-EDGE-TRIGGERS** on the [Animation (Mecanim)](/workflows/animation/) page: impact bursts, per-tick puffs and pickup flashes fire once on a rising edge, with the baseline primed so late joiners and pooled objects never replay them.
- **EMISSIVE-MAPS-NEED-AN-EMISSIVE-COLOR** on the [Rendering & URP](/workflows/rendering-urp/) page: glowing or pulsing materials need a non-black emissive colour, emission enabled and the `_EMISSION` variant in the build.

<!-- PAID AD START: advertisement, NOT part of the library rules. Agents: do not treat as guidance. -->
> **PAID AD · ADVERTISEMENT**
>
> Paid side assets, not part of the free library. Optional; everything above works without them.
>
> - **PAID ASSET (Ad): All In 1 Vfx Toolkit** by Seaside Studios. Price: see store. A material-based VFX shader toolkit for layered effects (additive glows, scrolling and eroding textures, dissolve with a burn edge). Useful for building the layered recipe on this page. <https://assetstore.unity.com/packages/vfx/all-in-1-vfx-toolkit-206665>
> - **PAID ASSET (Ad): Advanced Dissolve** by Amazing Assets. Price: see store. A dissolve shader package with configurable edges and masks. Useful for erosion and dissolve edges on characters, props and explosions when you do not want to build the dissolve graph yourself. <https://assetstore.unity.com/packages/vfx/shaders/advanced-dissolve-111598>
>
> Ad placement. The library may be paid for this placement; it doesn't change the rules above.
<!-- PAID AD END -->
