// 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(FindObjectsSortMode.None)) { if (candidate.lightType == Light2D.LightType.Global) { return candidate; } } return null; } }