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;
}
}