How to Create a Day Night Cycle in Unity

Transform your static game environments into immersive, living worlds with dynamic lighting, color changes, and time-based gameplay mechanics.

How to Create a Day Night Cycle in Unity Guide by Mayank Grover

Here's the thing about game development - I remember the exact moment I realized my games felt lifeless. I was at Carnegie Mellon, showing my professor this puzzle game I'd been working on for weeks. The mechanics were solid, the art wasn't terrible, but something was fundamentally wrong. "It feels static," he said. "Like a photograph instead of a living world."

That's when I discovered the magic of implementing day and night lighting in Unity. What started as a simple lighting experiment completely transformed how players experienced my game world. After months of tweaking and testing (and quite a few failures), I learned that a dynamic day night cycle in unity isn't just about pretty visuals - it's about creating worlds that breathe.

Let me show you exactly how to build this system, the way I wish someone had taught me back then.

Why Your Game World Feels Dead (And How to Fix It)

A dynamic day/night cycle is a system that simulates the progression of time within a game world, primarily through changing lighting conditions. This solves the problem of a static, lifeless environment by introducing a natural rhythm that enhances immersion and realism. It allows you to create worlds that feel alive, where the rising and setting of the sun can influence gameplay, trigger events, and alter the entire mood of a scene.

Think of it like a dimmer switch for a room's lights connected to a timer - as the timer progresses, the switch automatically adjusts the brightness and color of the light to mimic the transition from the bright, cool light of noon to the warm, dim glow of sunset, and finally to darkness. This automated change creates a dynamic atmosphere that can profoundly affect the player's experience and open up new avenues for game mechanics.

When I first started implementing this at KIXEYE, I had no idea how much it would change player engagement. Players started talking about their favorite time of day in the game, planning activities around the lighting changes. That's when I knew we were onto something special.

Dynamic Day Night Cycle Overview

The Foundation: Understanding Unity's Lighting Playground

Before scripting the cycle, it's crucial to understand the core components of Unity's lighting system that you will be manipulating. Been there - spent weeks trying to create dynamic lighting without understanding these fundamentals first.

Here's what I wish someone had told me earlier: master these components individually before trying to orchestrate them together. Trust me, you'll thank me later for this tip.

Three Ways I've Seen Day Night Cycle System in Unity Implemented

Implementation Approach Comparison Flowchart

The fundamental logic of a day/night cycle involves programmatically changing lighting properties over time. Each concept builds upon the last to create a cohesive and dynamic system.

Simulating Sun Movement via Rotation

The core of the cycle is achieved by continuously rotating the Directional Light around the X-axis to mimic the sun's arc across the sky.

csharp
// 3D Version
// This line rotates the light source around the world's X-axis.
// The speed of rotation is determined by time progression.
sun.transform.Rotate(Vector3.right, rotationSpeed * Time.deltaTime);

Controlling the Cycle's Duration

A public variable allows you to define the length of a full 24-hour cycle in seconds, making it easy to adjust the pacing of day and night transitions.

csharp
// This variable, exposed in the Inspector, sets the total duration of a day in real-world seconds.
public float dayDurationInSeconds = 60f;

Updating Ambient Light Color

To ensure the scene's overall brightness matches the time of day, the ambient light color is smoothly interpolated between different colors using a Gradient.

csharp
// 3D Version
// A Gradient allows you to define colors for different times of day (e.g., blue for night, orange for sunrise).
public Gradient ambientColor;

// The Evaluate() method samples the gradient based on the current time of day (a value from 0 to 1).
RenderSettings.ambientLight = ambientColor.Evaluate(timeOfDay);

Changing the Skybox Material

For more dramatic transitions, you can programmatically switch the entire Skybox material at different points in the cycle, such as swapping a sunny sky for a starry one.

csharp
// 3D Version
// This public variable holds a reference to the Material you want to use for the night skybox.
public Material nightSkybox;

// This line directly assigns a new material to the scene's skybox property.
RenderSettings.skybox = nightSkybox;

Updating 2D Global Light

In a 2D project using the Universal Render Pipeline (URP), you manipulate a Light2D component to change the color and intensity for all sprites set up to use 2D lighting.

csharp
// 2D Version
// This requires the 'UnityEngine.Rendering.Universal' namespace.
public Light2D globalLight;
public Gradient lightColor2D;

// The color of the global 2D light is updated based on the time of day.
globalLight.color = lightColor2D.Evaluate(timeOfDay);

Actually, wait - let me share something that took me months to figure out. When implementing day and night lighting, you have a choice between running logic in the Update method or using a Coroutine. Here's the breakdown:

Criteria Approach A: Update Method Approach B: Coroutine
Best For Simple, continuous logic that needs to run on every single frame, such as smoothly rotating the sun. Time-based sequences or logic that only needs to run periodically, like updating the weather every few minutes, which helps keep the Update method clean.
Performance Can be less performant if it contains complex checks that run every frame, even when not needed, as an empty Update call still has a small overhead. Generally more performant for infrequent tasks because it can pause its execution without consuming resources, avoiding unnecessary checks every frame.
Complexity Very straightforward for beginners to understand and implement for basic, constant changes. Slightly more complex syntax with IEnumerator and yield return, but offers powerful control over timing and sequencing of events.
Code Example void Update() { sun.Rotate(Vector3.right * speed * Time.deltaTime); } IEnumerator UpdateLighting() { while(true) { sun.Rotate(Vector3.right * speed); yield return new WaitForSeconds(0.1f); } }

Here's How I Build the Basic Sun Rotation Every Time

Let me walk you through my exact process for creating a basic day night cycle in unity. This is the foundation I use in every project, and after working on multiple Unity projects, I can tell you this approach has never failed me.

Step 1: Unity Editor Setup

Step 2: Declare Variables

csharp
using UnityEngine;

public class DayNightCycle : MonoBehaviour
{
    [Tooltip("The Directional Light representing the sun in the scene.")]
    public Light sun;

    [Tooltip("The duration of a full day-night cycle in real-world seconds.")]
    public float dayDurationSeconds = 120f; 
}

Step 3: Implement the Rotation Logic

csharp
void Update()
{
    if (sun == null) return; // Don't run if the sun isn't assigned.

    // Calculate the rotation angle per second based on the total duration.
    // We rotate 360 degrees over the course of the dayDurationSeconds.
    float rotationSpeed = 360f / dayDurationSeconds;

    // Rotate the sun around the world's X-axis.
    // Time.deltaTime ensures the rotation is smooth and frame-rate independent.
    sun.transform.Rotate(Vector3.right, rotationSpeed * Time.deltaTime);
}

Step 4: Assign in Editor

Go back to the Unity Editor. Select the "DayNightController" GameObject. Drag the "Sun" Directional Light from your Hierarchy into the "Sun" field of your DayNightCycle script component in the Inspector. Press Play to see the light rotate and the shadows move across your scene.

Basic Sun Rotation Implementation in Unity

Taking It Further: When Your World Changes Color

Here's where things get exciting. The basic rotation is just the beginning - let me show you how I enhance the cycle with dynamic lighting and skybox changes. This is the technique I've seen used brilliantly in games like Breath of the Wild.

Enhanced Variables Setup:

csharp
using UnityEngine;

public class DayNightCycle : MonoBehaviour
{
    public Light sun;
    public float dayDurationSeconds = 120f;

    [Header("Lighting Settings")]
    [Tooltip("Controls the color of the ambient light throughout the day.")]
    public Gradient ambientColor;
    [Tooltip("Controls the color of the scene's fog throughout the day.")]
    public Gradient fogColor;
    [Tooltip("Controls the tint of the procedural skybox throughout the day.")]
    public Gradient skyboxTint;

    private float timeOfDay; // A value from 0 (midnight) to 1 (next midnight).
}

Time and Lighting Update Logic:

csharp
void Update()
{
    if (sun == null) return;

    // Increment timeOfDay based on the duration.
    // Time.deltaTime / dayDurationSeconds gives us the percentage of the day that has passed in this frame.
    timeOfDay += Time.deltaTime / dayDurationSeconds;
    timeOfDay %= 1; // Use modulo to wrap the value back to 0 when it reaches 1.

    // Rotate the sun based on the time of day.
    // timeOfDay * 360f converts our 0-1 value into a 0-360 degree rotation.
    sun.transform.rotation = Quaternion.Euler(timeOfDay * 360f, 0, 0);

    // Update the environment lighting based on the gradients.
    UpdateLighting(timeOfDay);
}

private void UpdateLighting(float currentTime)
{
    // Sample the gradients at the current time of day.
    RenderSettings.ambientLight = ambientColor.Evaluate(currentTime);
    RenderSettings.fogColor = fogColor.Evaluate(currentTime);

    // Update the procedural skybox tint if the skybox material is assigned.
    if (RenderSettings.skybox != null && RenderSettings.skybox.HasProperty("_Tint"))
    {
        RenderSettings.skybox.SetColor("_Tint", skyboxTint.Evaluate(currentTime));
    }

    // Tell Unity's GI to update with the new environmental lighting.
    DynamicGI.UpdateEnvironment();
}

The 2D Approach That Actually Works

When I'm working on 2D projects, my process is completely different. Here's my tried-and-tested setup for 2D projects using the Universal Render Pipeline (URP):

2D Setup Process:

2D Variables Declaration:

csharp
using UnityEngine;
using UnityEngine.Rendering.Universal; // Required for Light2D

public class DayNightCycle2D : MonoBehaviour
{
    [Tooltip("The Global Light 2D that will act as the sun.")]
    public Light2D globalLight;

    [Tooltip("The duration of a full day-night cycle in real-world seconds.")]
    public float dayDurationSeconds = 60f;

    [Tooltip("Controls the color and intensity of the global 2D light.")]
    public Gradient lightColor;

    private float timeOfDay;
}

2D Implementation Logic:

csharp
void Update()
{
    if (globalLight == null) return;

    // Increment and wrap the time of day, same as the 3D version.
    timeOfDay += Time.deltaTime / dayDurationSeconds;
    timeOfDay %= 1;

    // Update the global light's color by evaluating the gradient.
    UpdateGlobalLight(timeOfDay);
}

private void UpdateGlobalLight(float currentTime)
{
    globalLight.color = lightColor.Evaluate(currentTime);
}

Real Games That Nail This (And What You Can Learn)

Let me tell you about some implementations that have really impressed me over the years. I always tell my students to study these approaches:

Minecraft - The Survival Rhythm Master

What I find fascinating about this approach is how the game features a distinct cycle where daytime is for gathering and building, while nighttime introduces dangerous monsters that spawn in the darkness. The implementation uses a simple rotation of the directional light to control the sun's position. The light's angle is likely used to determine the time of day, which in turn triggers a change in game state, enabling monster spawners when the light level drops below a certain threshold.

Here's how you can adapt this for your own game:

csharp
// A simplified concept of checking light angle to trigger events.
public Light sun;
private bool isNight = false;

void CheckForNight()
{
    // When the sun's rotation passes the horizon (e.g., 180 degrees), it's night.
    if (sun.transform.eulerAngles.x > 180 && !isNight)
    {
        isNight = true;
        // Code to enable monster spawning would go here.
        Debug.Log("Night has fallen. Monsters will now spawn.");
    }
    else if (sun.transform.eulerAngles.x < 180 && isNight)
    {
        isNight = false;
        // Code to disable monster spawning.
        Debug.Log("The sun is rising. Monsters will burn.");
    }
}

The Legend of Zelda: Breath of the Wild - The Living World

After analyzing dozens of games, this stands out because the time of day affects the environment, NPC schedules, and the types of creatures that appear. For example, Stal-enemies (skeletons) emerge from the ground only at night. The system likely uses a global time variable that progresses continuously, driving the sun's rotation, skybox changes, and ambient lighting.

From a developer's perspective, what makes this brilliant is the event system:

csharp
// A simplified event-based approach for time-of-day mechanics.
public static event System.Action OnNightFall;

void TriggerNightEvents()
{
    // When the condition for night is met, invoke the event.
    if (OnNightFall != null)
    {
        OnNightFall.Invoke();
    }
}

// Another script (e.g., an enemy spawner) would subscribe to this event.
void OnEnable() { DayNightController.OnNightFall += SpawnStalEnemies; }
void OnDisable() { DayNightController.OnNightFall -= SpawnStalEnemies; }
void SpawnStalEnemies() { /* ... spawning logic ... */ }

Dying Light - The Fear Factor

This is why I always recommend studying this game's approach. The transition to night dramatically increases the danger, turning the game from a parkour action game into a tense survival horror experience. A state machine controls the game's difficulty and enemy types based on the day/night cycle.

Here's the concept you can implement:

csharp
// A simple state machine concept for managing game difficulty.
public enum GameState { Day, Night }
public GameState currentState;

void SetState(GameState newState)
{
    currentState = newState;
    if (currentState == GameState.Night)
    {
        // Increase difficulty, change music, spawn Volatiles.
        Debug.Log("WARNING: Night is here. Volatiles are hunting.");
    }
    else
    {
        // Revert to normal daytime settings.
        Debug.Log("Daybreak. It is safe to go outside.");
    }
}

My Step-by-Step Implementation Blueprint

Let me show you how I approach this in my projects. These are the exact settings I use, and I've configured this dozens of times with these same steps:

Pro Tip 1: Always Instantiate Skybox Material at Runtime

I learned this the hard way - to prevent your script from permanently changing the skybox material asset in the editor after exiting play mode, you should create a temporary instance of it on start:

csharp
// 3D Version
void Awake()
{
    // Create a runtime copy of the skybox material to avoid overwriting the original asset file.
    RenderSettings.skybox = Instantiate(RenderSettings.skybox);
}

Pro Tip 2: Use Gradients for Smooth Transitions

Instead of abruptly changing colors, use Unity's Gradient class to define a smooth spectrum of colors. I've found this works best when you configure the gradients properly:

csharp
// This Gradient can be configured in the Inspector to map colors to the 0-1 time of day value.
public Gradient fogColorGradient;

// Evaluate the gradient at the current time to get the correct color.
RenderSettings.fogColor = fogColorGradient.Evaluate(timeOfDay);

Pro Tip 3: Update Global Illumination for Dynamic Lighting

When changing the skybox or ambient light, you must tell Unity's dynamic global illumination system to update so that bounced lighting accurately reflects the new environment:

csharp
// 3D Version
// This function call forces the environmental lighting to be recalculated.
// It's crucial for making sure bounced light matches the current skybox.
DynamicGI.UpdateEnvironment();

Pro Tip 4: Manage Night-Time Lights Efficiently

Trust me, you'll thank me later for this tip. Activating many individual lights at night can severely impact performance. I always use this distance-based optimization:

csharp
// This example assumes you have an array of Light components.
public Light[] nightLights;
public Transform player;
public float activationDistance = 50f;

void UpdateNightLights()
{
    foreach (Light light in nightLights)
    {
        // Check the distance between the player and each light.
        float distance = Vector3.Distance(player.position, light.transform.position);
        // Enable the light only if the player is close enough.
        light.enabled = (distance < activationDistance);
    }
}

What You'll Gain From Mastering This

Implementing a dynamic day/night cycle is more than just a visual enhancement - it provides significant advantages that can elevate your game:

After working on multiple Unity projects, I can tell you that mastering this system will fundamentally change how players experience your games. It's one of those features that transforms a good game into a memorable one.


Key Takeaways

Common Questions

What is a day night cycle in unity and why do I need it?+

A day night cycle in unity is a system that automatically changes your game's lighting over time to simulate the passage of a full day. You need it because it makes your game world feel alive and dynamic instead of static, which significantly improves player immersion and opens up new gameplay possibilities.

How do I create day and night cycle in unity for beginners?+

Start with the basic approach: create a Directional Light representing the sun, then use a script to continuously rotate it around the X-axis using sun.transform.Rotate(Vector3.right, rotationSpeed * Time.deltaTime). This creates the foundation for all other lighting changes.

What's the difference between implementing day and night lighting in 2D vs 3D Unity projects?+

In 3D projects, you rotate a Directional Light and modify RenderSettings properties. In 2D projects using URP, you modify a Light2D component's color and intensity properties instead of rotating lights. The 2D approach requires the UnityEngine.Rendering.Universal namespace.

When should I use Update() versus Coroutines for day night cycle system in unity?+

Use Update() for smooth, continuous changes like sun rotation that need frame-perfect precision. Use Coroutines for periodic updates like weather changes or events that only need to check every few seconds, as they're more performance-friendly for infrequent tasks.

How do I make smooth color transitions during day and night changes?+

Use Unity's Gradient class to define color ranges for different times of day, then evaluate the gradient using your timeOfDay value: RenderSettings.ambientLight = ambientColor.Evaluate(timeOfDay). This creates smooth transitions between all your defined colors.

What is DynamicGI.UpdateEnvironment() and when do I need it?+

DynamicGI.UpdateEnvironment() forces Unity's Global Illumination system to recalculate bounced lighting when you change environmental lighting properties. Call it whenever you modify the skybox, ambient light, or other environmental settings to ensure realistic light bouncing.

How do I prevent my skybox material from being permanently changed in the editor?+

In your Awake() method, create a runtime instance of the skybox material using RenderSettings.skybox = Instantiate(RenderSettings.skybox). This creates a temporary copy that won't affect your original asset files.

What causes performance issues with implementing day and night lighting?+

The main performance killer is activating too many individual lights simultaneously during night time. Optimize by using distance-based light activation - only enable lights within a certain range of the player using Vector3.Distance() checks.

How do I trigger events based on time of day in my day night cycle system in unity?+

Use a time-checking system that compares the sun's rotation or timeOfDay value, then invoke events when thresholds are crossed. For example, check if sun.transform.eulerAngles.x > 180 to detect nightfall and trigger appropriate events like enemy spawning.

Can I use different skybox materials for day and night?+

Yes, you can programmatically switch skybox materials using RenderSettings.skybox = nightSkybox where nightSkybox is a public Material variable. This allows for dramatic visual changes like switching from a sunny sky to a starry night sky.