unity-lighting-vfx

Installation
SKILL.md

Unity Lighting and Visual Effects

Lighting Modes

Unity provides three light modes controlling how illumination is calculated.

Realtime Lights

  • Calculate lighting every frame at runtime
  • Allow dynamic changes to intensity, color, position
  • Cast shadows up to Shadow Distance
  • Contribute only direct lighting by default (no bounced light)
  • Higher runtime cost, especially in complex scenes or low-end hardware
  • Best for: dynamic objects, flickering effects, moving light sources

Baked Lights

  • Calculations performed in the Unity Editor and saved as lighting data to disk
  • At runtime, Unity loads pre-computed data instead of calculating dynamically
  • Bake both direct and indirect lighting into lightmaps
  • Store information in Light Probes for moving objects
  • Cannot modify light properties at runtime; do not illuminate dynamic GameObjects
  • No specular contributions
  • Best for: static scenery, complex indirect lighting, performance-critical scenarios

Mixed Lights

  • Combine baked indirect lighting with real-time direct lighting
  • Behavior depends on the Lighting Mode setting in the Lighting window
  • Cast real-time shadows (not baked soft shadows)
  • Can change properties at runtime (affects real-time component only)
  • Always more expensive than fully baked lighting
  • Best for: dynamic shadows with baked background lighting

Important: All baked/mixed modes require Baked Global Illumination enabled. Without it, Mixed and Baked lights behave as Realtime.

Light Types

Directional Light

  • Located infinitely far away, emits light in one direction
  • Parallel rays, no distance-based intensity falloff
  • Simulates sun/moon; every new scene includes one by default
  • Links to procedural sky system; rotate to create time-of-day effects

Point Light

  • Located at a point, emits in all directions equally
  • Intensity follows inverse square law (diminishes with distance squared)
  • Use for lamps, explosions, local illumination

Spot Light

  • Located at a point, emits in a cone shape
  • Adjustable cone angle; light diminishes at edges (penumbra)
  • Wider angles create larger fade areas
  • Use for flashlights, headlights, searchlights

Area Light

  • Defined by a rectangle or disc; emits uniformly across surface
  • Follows inverse square law; produces soft, subtle shading
  • Bake-only -- not available at runtime
  • Use for street lights, realistic interior lighting

Global Illumination

Global illumination (GI) simulates how light bounces between surfaces, producing realistic indirect lighting.

Baked GI

  • Pre-computes indirect lighting into lightmaps using the Progressive Lightmapper (CPU or GPU)
  • Results stored in lightmap textures and Light Probes
  • Configure in the Lighting window under Bake settings
  • GPU Progressive Lightmapper offers faster bake times with configurable tile sizes

Environment Lighting

Three ambient light sources configured in the Lighting window Environment tab:

  • Skybox: Uses skybox material colors for ambient light from different angles
  • Gradient: Separate sky, horizon, and ground colors with smooth blending
  • Color: Uniform ambient light across the scene

Intensity Multiplier (0-8, default 1) controls ambient brightness.

Environment Reflections

  • Source: Skybox or custom Cubemap/RenderTexture
  • Configurable resolution, compression, intensity multiplier
  • Bounces setting controls reflection evaluation iterations between objects

Light Probes and Adaptive Probe Volumes

Light Probes

  • Capture lighting information in empty space throughout a scene
  • At runtime, indirect lighting for dynamic GameObjects is approximated using nearest probes
  • Provide indirect bounced light for moving objects and LOD system support
  • Must be manually placed using Light Probe Groups
  • Store baked lighting information; work with both direct and indirect lighting

Adaptive Probe Volumes (APV)

APV is the modern replacement for manual Light Probe placement in URP:

  • Automated probe placement -- eliminates manual Light Probe Group positioning
  • Per-pixel lighting -- superior quality compared to per-object approaches
  • Scene baking -- bake multiple scenes together using Baking Sets
  • Runtime adjustments -- Lighting Scenarios and sky occlusion for dynamic changes
  • Large-world support -- streaming data for expansive open-world environments
  • Data flexibility -- loading from AssetBundles or Addressables
  • Configurable probe density and volume size with visualization tools

Reflection Probes

Capture a spherical view of surroundings as a cubemap for reflective materials.

Types

Type Description
Baked Captures static GameObjects only; best performance
Custom Allows dynamic object capture with custom textures
Realtime Updates during gameplay; configurable refresh mode

Key Properties

  • Importance: Rendering priority when multiple probes overlap
  • Intensity: Texture brightness in shader calculations
  • Box Projection: Enables projection mapping for interiors (requires URP config)
  • Box Size/Offset: World-space bounding box for reflection contribution
  • Blend Distance: Blending distance for deferred probes

Realtime Options

  • Refresh Mode: On Awake, Every Frame, or Via Scripting
  • Time Slicing: All Faces At Once, Individual Faces, No Time Slicing

Particle System vs VFX Graph

Feature Particle System VFX Graph
Simulation CPU-based GPU-based
Particle count Thousands Millions
Render pipeline All pipelines URP/HDRP only
Authoring Inspector modules Node-based graph editor
Physics Built-in collision Custom collision blocks
Scripting Full C# API Event-based C# API
Sub-emitters Native support GPU Event contexts
Best for Small/medium effects, mobile Large-scale effects, high-end

Decision Guide:

  • Use Particle System for mobile targets, simple effects, when you need full CPU-side scripting control, or when targeting the Built-in Render Pipeline
  • Use VFX Graph for massive particle counts, GPU-driven simulations, complex node-based authoring, or high-end platforms with URP/HDRP

Particle System Modules

Module Purpose
Main Initial state: lifetime, speed, size, gravity, simulation space
Emission Rate and timing of particle spawns
Shape Volume/surface for emission and start velocity direction
Velocity over Lifetime Modify movement over particle age
Noise Turbulence for organic, chaotic motion
Limit Velocity over Lifetime Natural deceleration
Force over Lifetime Simulated physics forces
Inherit Velocity Sub-emitter particles match parent velocity
Lifetime by Emitter Speed Adjust lifespan based on emitter velocity
Color over Lifetime / by Speed Color changes based on age or velocity
Size over Lifetime / by Speed Dimension changes based on time or speed
Rotation over Lifetime / by Speed Orientation changes
Collision Particle collisions with scene geometry
Triggers Designate particles as collision triggers
Sub Emitters Particles that emit other particles
Texture Sheet Animation Texture grid animation frames
Trails Motion trail rendering
Lights Real-time lights on particles
External Forces Wind zones and force fields
Renderer Image/mesh transform, shading, overdraw
Custom Data Attach custom data to particles

VFX Graph Basics

Systems

  1. Spawn System: Single Spawn Context managing emission
  2. Particle System: Initialize -> Update -> Output succession
  3. Mesh Output System: Single Mesh Output Context

Contexts

  • Spawn: Executes each frame to calculate spawn amounts. States: Running, Idle, Waiting. Configurable loop duration, count, and delays
  • Initialize: Runs at particle birth, sets initial state. Processes Blocks for newly spawned particles. Configurable bounds and capacity
  • Update: Per-frame for all living particles. Automatic: position integration, rotation integration, aging, reaping
  • Output: Renders particles (Quad, Mesh, etc.). No output ports. Customizable rendering blocks

Graph Elements

  • Blocks: Stackable nodes within Contexts; each handles one operation; top-to-bottom execution
  • Operators: Low-level property workflow nodes connecting to Block/Context ports
  • Properties: Connectable via property workflow
  • Settings: Non-connectable editable values per Context

GPU Events

Experimental feature where GPU computes events (vs CPU for normal events). Cannot be customized with Blocks.

Common Patterns (C#)

Create and Configure a Light

using UnityEngine;

public class LightSetup : MonoBehaviour
{
    void Start()
    {
        GameObject lightObj = new GameObject("Dynamic Light");
        Light light = lightObj.AddComponent<Light>();
        light.type = LightType.Point;
        light.color = Color.yellow;
        light.intensity = 2.0f;
        light.range = 15f;
        light.shadows = LightShadows.Soft;
        light.shadowResolution = UnityEngine.Rendering.LightShadowResolution.Medium;
    }
}

Create a Realtime Reflection Probe

using UnityEngine;
using UnityEngine.Rendering;

public class ProbeSetup : MonoBehaviour
{
    void Start()
    {
        GameObject probeObj = new GameObject("Realtime Reflection Probe");
        ReflectionProbe probe = probeObj.AddComponent<ReflectionProbe>();
        probe.size = new Vector3(10, 10, 10);
        probe.mode = ReflectionProbeMode.Realtime;
        probe.refreshMode = ReflectionProbeRefreshMode.EveryFrame;
        probe.resolution = 256;
        probe.hdr = true;
    }
}

Control Particle System at Runtime

using UnityEngine;

public class ParticleController : MonoBehaviour
{
    ParticleSystem ps;

    void Start()
    {
        ps = GetComponent<ParticleSystem>();

        // Modify emission rate -- cache module in local variable first
        var emission = ps.emission;
        emission.rateOverTimeMultiplier = 50f;

        // Modify main module
        var main = ps.main;
        main.startLifetime = 3f;
        main.startSpeed = 5f;
        main.simulationSpace = ParticleSystemSimulationSpace.World;
    }

    void OnTriggerEnter(Collider other)
    {
        // Burst emit particles
        ps.Emit(100);
    }

    void OnDisable()
    {
        ps.Stop(true, ParticleSystemStopBehavior.StopEmittingAndClear);
    }
}

VFX Graph Runtime Control

using UnityEngine;
using UnityEngine.VFX;

public class VFXController : MonoBehaviour
{
    VisualEffect vfx;
    VFXEventAttribute eventAttr;

    void Start()
    {
        vfx = GetComponent<VisualEffect>();
        eventAttr = vfx.CreateVFXEventAttribute();

        // Set exposed properties
        vfx.SetFloat("SpawnRate", 100f);
        vfx.SetVector3("Direction", Vector3.up);
        vfx.playRate = 1.5f;
    }

    void OnTriggerEnter(Collider other)
    {
        // Send custom event with attributes
        eventAttr.SetVector3("position", other.transform.position);
        vfx.SendEvent("OnHit", eventAttr);
    }

    public void StopEffect()
    {
        vfx.Stop();
    }
}

Refresh Reflection Probe on Demand

using UnityEngine;

public class ProbeRefresher : MonoBehaviour
{
    ReflectionProbe probe;

    void Start()
    {
        probe = GetComponent<ReflectionProbe>();
        probe.refreshMode = UnityEngine.Rendering.ReflectionProbeRefreshMode.ViaScripting;
    }

    public void RefreshReflections()
    {
        probe.RenderProbe();
    }

    public bool IsReady()
    {
        return probe.IsFinishedRendering(probe.RenderProbe());
    }
}

Anti-Patterns

Lighting Anti-Patterns

  1. Too many Realtime lights: Each realtime light adds per-frame cost. Use Baked or Mixed for static lights
  2. Forgetting to enable Baked Global Illumination: Mixed/Baked lights silently fall back to Realtime without it
  3. Overlapping Reflection Probes without Importance values: Causes flickering; always set Importance to establish priority
  4. Using Area Lights expecting runtime behavior: Area lights are bake-only; they produce no light at runtime
  5. Ignoring Indirect Multiplier: Leaving at default can cause over-bright or too-dark bounced light; tune per light
  6. Not setting Shadow Bias correctly: Too low causes self-shadowing artifacts (shadow acne); too high causes peter-panning (shadows detach from objects)
  7. Manual Light Probe placement in large scenes: Use Adaptive Probe Volumes (APV) in URP instead for automated, per-pixel quality

Particle System Anti-Patterns

  1. Not caching module references: Each property access on a module struct immediately writes to native code; cache the module variable
  2. Using World simulation space for attached effects: Particles drift away from moving parents; use Local space for attached FX
  3. Excessive particle counts on CPU: Particle System is CPU-bound; for >10K particles, consider VFX Graph
  4. Forgetting to Stop/Clear: Leaked particle systems consume CPU even when invisible

VFX Graph Anti-Patterns

  1. Using VFX Graph for simple effects on mobile: GPU overhead and URP/HDRP requirement make it overkill for simple mobile effects
  2. Not setting Capacity in Initialize: Default capacity may allocate too much or too little GPU memory
  3. Ignoring Bounds: Incorrect bounds cause effects to be culled when visible; always configure bounds in Initialize context
  4. Sending events every frame without throttling: SendEvent has CPU-GPU sync cost; batch or throttle event dispatch

Key API Quick Reference

Light (UnityEngine.Light)

Member Type Description
type Property LightType (Directional, Point, Spot, Area)
color Property Emitted light color
intensity Property Brightness multiplier
range Property Max distance (Point/Spot)
spotAngle / innerSpotAngle Property Outer/inner cone angles
shadows Property LightShadows (None, Hard, Soft)
shadowResolution Property Shadow map quality
shadowBias / shadowNormalBias Property Shadow artifact reduction
bounceIntensity Property GI bounce strength
cookie Property Projected texture mask
cullingMask Property Layer-based filtering
colorTemperature Property CCT in Kelvin
lightmapBakeType Property Baking configuration
bakingOutput Property Last bake contribution details
AddCommandBuffer() Method Execute GPU commands at specified points

ParticleSystem (UnityEngine.ParticleSystem)

Member Type Description
main / emission / shape Property Module access structs
particleCount Property Current active particles
isPlaying / isPaused / isStopped Property Playback state
Play() / Pause() / Stop() Method Playback control
Emit(count) Method Immediate particle spawn
Simulate(time) Method Fast-forward simulation
GetParticles() / SetParticles() Method Direct particle data access
Clear() Method Remove all particles
TriggerSubEmitter() Method Activate sub-emitters

VisualEffect (UnityEngine.VFX.VisualEffect)

Member Type Description
visualEffectAsset Property Assign/change effect graph
playRate Property Simulation speed
aliveParticleCount Property Active particle count
Play() / Stop() / Reinit() Method Playback control
SendEvent(name, attr) Method Trigger graph events
CreateVFXEventAttribute() Method Create event payload
SetFloat() / SetVector3() / etc. Method Set exposed properties
GetFloat() / GetVector3() / etc. Method Read exposed properties
HasFloat() / HasVector3() / etc. Method Check property existence
ResetOverride(property) Method Restore original values

ReflectionProbe (UnityEngine.ReflectionProbe)

Member Type Description
mode Property Baked/Custom/Realtime
size / center Property Bounding box config
intensity / importance Property Brightness and priority
boxProjection Property Enable box projection
refreshMode / timeSlicingMode Property Realtime update config
RenderProbe() Method Force cubemap refresh
IsFinishedRendering() Method Check time-sliced completion
BlendCubemap() Method Blend two cubemaps

Related Skills

  • unity-graphics -- Render pipelines (URP/HDRP/Built-in), shaders, materials, cameras
  • unity-2d -- 2D lighting (URP 2D Renderer), sprite rendering
  • unity-platforms -- Platform-specific lighting quality tiers, mobile optimization

Additional Resources

Weekly Installs
7
GitHub Stars
8
First Seen
Mar 19, 2026
Installed on
amp6
cline6
opencode6
cursor6
kimi-cli6
warp6