Source file unity-csharp/2d-lighting/TorchFlicker2D.cs from the GDnD code examples. Download raw file

// GDnD wiki example
// Demonstrates: a flickering torch or candle made by driving Light2D.intensity and pointLightOuterRadius with Perlin noise
// Related pages: [[unity-2d-lighting]], [[lighting-for-mood-and-guidance]]
 
using UnityEngine;
using UnityEngine.Rendering.Universal; // Light2D lives in the URP package
 
// Put this on a GameObject that has a Light 2D component set to Light Type: Spot.
// Perlin noise changes smoothly, so the flame wavers instead of strobing the way
// Random.Range would every frame.
[RequireComponent(typeof(Light2D))]
public class TorchFlicker2D : MonoBehaviour
{
    [Header("Intensity")]
    [SerializeField] private float baseIntensity = 1.2f;
    [SerializeField] private float intensityVariation = 0.35f;
 
    [Header("Radius (Spot lights only)")]
    [SerializeField] private float baseOuterRadius = 4f;
    [SerializeField] private float radiusVariation = 0.3f;
 
    [Header("Speed")]
    [Tooltip("How fast the flicker changes. 2 to 6 suits a torch; above 10 looks electrical.")]
    [SerializeField] private float flickerSpeed = 4f;
 
    private Light2D light2D;
    private float noiseOffset;
 
    private void Awake()
    {
        light2D = GetComponent<Light2D>();
 
        // A different starting point in the noise for each torch, so a row of
        // torches does not flicker in perfect step.
        noiseOffset = Random.Range(0f, 1000f);
    }
 
    private void Update()
    {
        float t = Time.time * flickerSpeed + noiseOffset;
 
        // PerlinNoise returns roughly 0..1; shift it to -1..1 so the light
        // goes both brighter and dimmer than its base value.
        float flicker = Mathf.PerlinNoise(t, 0f) * 2f - 1f;
 
        light2D.intensity = Mathf.Max(0f, baseIntensity + flicker * intensityVariation);
 
        // Sample a second row of the noise so size and brightness are not identical.
        if (light2D.lightType == Light2D.LightType.Point) // shown as "Spot" in the Inspector
        {
            float sizeFlicker = Mathf.PerlinNoise(t, 7.3f) * 2f - 1f;
            light2D.pointLightOuterRadius = Mathf.Max(0.1f, baseOuterRadius + sizeFlicker * radiusVariation);
        }
    }
 
    private void OnValidate()
    {
        baseIntensity = Mathf.Max(0f, baseIntensity);
        baseOuterRadius = Mathf.Max(0.1f, baseOuterRadius);
        flickerSpeed = Mathf.Max(0f, flickerSpeed);
    }
}