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

// GDnD wiki example
// Demonstrates: a day-night cycle that drives a Global Light 2D's colour and intensity, and switches night lights on after dusk
// Related pages: [[unity-2d-lighting]], [[lighting-for-mood-and-guidance]]
 
using UnityEngine;
using UnityEngine.Rendering.Universal;
 
// Put this on any GameObject (an empty "Lighting" object is tidy) and drag in the
// scene's Global Light 2D. Edit the Gradient and Curve in the Inspector to shape the day.
public class DayNightCycle2D : MonoBehaviour
{
    [SerializeField] private Light2D globalLight;
 
    [Tooltip("Real seconds for one full day. 120 is quick enough to watch while testing.")]
    [SerializeField] private float secondsPerDay = 120f;
 
    [Tooltip("0 = midnight, 0.25 = dawn, 0.5 = noon, 0.75 = dusk.")]
    [Range(0f, 1f)]
    [SerializeField] private float timeOfDay = 0.3f;
 
    [Tooltip("Light colour across the day, left = midnight, right = the next midnight.")]
    [SerializeField] private Gradient skyColour = new Gradient();
 
    [Tooltip("Global light intensity across the day (x = time of day 0..1).")]
    [SerializeField] private AnimationCurve skyIntensity = AnimationCurve.Linear(0f, 1f, 1f, 1f);
 
    [Header("Night lights (torches, windows, street lamps)")]
    [SerializeField] private Light2D[] nightLights;
    [Tooltip("Night lights switch on when the global intensity falls below this value.")]
    [SerializeField] private float nightLightThreshold = 0.4f;
 
    public float TimeOfDay => timeOfDay;
 
    private void Update()
    {
        if (globalLight == null || secondsPerDay <= 0f)
        {
            return;
        }
 
        // Advance and wrap round at the end of the day.
        timeOfDay = Mathf.Repeat(timeOfDay + Time.deltaTime / secondsPerDay, 1f);
 
        float intensity = skyIntensity.Evaluate(timeOfDay);
        globalLight.color = skyColour.Evaluate(timeOfDay);
        globalLight.intensity = intensity;
 
        bool isNight = intensity < nightLightThreshold;
        foreach (Light2D nightLight in nightLights)
        {
            if (nightLight != null && nightLight.enabled != isNight)
            {
                nightLight.enabled = isNight;
            }
        }
    }
 
    // Reset runs in the Editor when the component is first added (or via the
    // component's Reset menu item), so it is a safe place to fill in a starter day.
    private void Reset()
    {
        globalLight = FindGlobalLight();
 
        skyIntensity = new AnimationCurve(
            new Keyframe(0f, 0.15f), new Keyframe(0.25f, 0.5f), new Keyframe(0.5f, 1f),
            new Keyframe(0.75f, 0.5f), new Keyframe(1f, 0.15f));
 
        skyColour = new Gradient();
        skyColour.SetKeys(
            new[]
            {
                new GradientColorKey(new Color(0.25f, 0.30f, 0.60f), 0f),    // midnight blue
                new GradientColorKey(new Color(1.00f, 0.65f, 0.45f), 0.25f), // dawn orange
                new GradientColorKey(Color.white, 0.5f),                     // noon
                new GradientColorKey(new Color(1.00f, 0.55f, 0.40f), 0.75f), // dusk
                new GradientColorKey(new Color(0.25f, 0.30f, 0.60f), 1f),    // midnight again
            },
            new[] { new GradientAlphaKey(1f, 0f), new GradientAlphaKey(1f, 1f) });
    }
 
    private static Light2D FindGlobalLight()
    {
        foreach (Light2D candidate in FindObjectsByType<Light2D>(FindObjectsSortMode.None))
        {
            if (candidate.lightType == Light2D.LightType.Global)
            {
                return candidate;
            }
        }
        return null;
    }
}