File size: 2,402 Bytes
40c0886
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
using UnityEngine;

namespace UnityAgent
{
    /// <summary>
    /// Rotates a directional light around the world to simulate a day/night
    /// cycle. Also lerps between day and night sky/ambient colors and turns
    /// street lights on after sunset.
    /// </summary>
    public class DayNightCycle : MonoBehaviour
    {
        [Header("Sun")]
        public Light sun;
        public float dayLengthSeconds = 120f;

        [Header("Colors")]
        public Color daySky = new Color(0.5f, 0.7f, 1.0f);
        public Color nightSky = new Color(0.03f, 0.04f, 0.08f);
        public Color dayAmbient = new Color(0.6f, 0.6f, 0.6f);
        public Color nightAmbient = new Color(0.12f, 0.13f, 0.18f);

        [Header("Lights")]
        public Light[] streetLights;
        public float streetLightThreshold = 0.2f;

        private float _timeOfDay; // 0..1

        private void Start()
        {
            if (sun == null) sun = GetComponent<Light>();
            RenderSettings.ambientMode = UnityEngine.Rendering.AmbientMode.Flat;
        }

        private void Update()
        {
            _timeOfDay = (_timeOfDay + Time.deltaTime / dayLengthSeconds) % 1f;

            // Sun angle: at timeOfDay=0.25 sun is at noon.
            float sunAngle = (_timeOfDay - 0.25f) * 360f;
            if (sun != null)
            {
                sun.transform.rotation = Quaternion.Euler(sunAngle, -30f, 0f);
                float dayFactor = Mathf.Clamp01(Mathf.Cos((_timeOfDay - 0.25f) * Mathf.PI * 2f) * 0.5f + 0.5f);
                sun.intensity = dayFactor * 1.2f;
            }

            float t = Mathf.Clamp01(Mathf.Cos((_timeOfDay - 0.25f) * Mathf.PI * 2f) * 0.5f + 0.5f);
            RenderSettings.ambientLight = Color.Lerp(nightAmbient, dayAmbient, t);
            Camera mainCam = Camera.main;
            if (mainCam != null)
            {
                mainCam.backgroundColor = Color.Lerp(nightSky, daySky, t);
            }

            UpdateStreetLights(t);
        }

        private void UpdateStreetLights(float dayFactor)
        {
            if (streetLights == null) return;
            bool on = dayFactor < streetLightThreshold;
            foreach (var l in streetLights)
                if (l != null) l.enabled = on;
        }

        /// <summary>Current time of day in 0..1 range (0=midnight).</summary>
        public float TimeOfDay => _timeOfDay;
    }
}