using System; using System.Collections; using TMPro; using UnityEngine; using UnityEngine.Rendering.Universal; public class DayNightCycleManager : MonoBehaviour { // possible future additions // weather sys // skybox changes based on time of day // moon and stars // clouds // rain // Sound effects, bird chrirping, crickets, wind, etc // Temperture? // Lighting effects! So that the transition is more visually appealing // Moonlight phases based on day of month ect // Seasons - impact the length of day, temp, weather, etc public enum Season { Spring, Summer, Autumn, Winter } public float dayLengthInMinutes = 15f; public float startTimeInHours = 6f; // Start time in hours public Light2D globalLight; public TMP_Text timeText; public TMP_Text dayText; public TMP_Text seasonText; public Gradient lightColorGradient; public Gradient lightIntensityGradient; public bool isFirstDay = true; public int monthsPerYear = 4; public int daysPerMonth = 28; private Season _currentSeason; private float _currentTime; private int _daysPassed; private void Start() { _currentTime = isFirstDay ? startTimeInHours / 24 * dayLengthInMinutes * 60 : 0; StartCoroutine(DayNightCycleCoroutine()); isFirstDay = false; } private void Update() { timeText.text = GetCurrentTime(); // todo: optimize to only update on day change dayText.text = GetCurrentDayOfMonth().ToString(); seasonText.text = GetCurrentSeason().ToString(); } public static event Action OnDayChange; public static event Action OnSeasonChange; public Season GetCurrentSeason() { // Calculate the current day of the year var month = GetCurrentMonth(); return month switch { 0 => Season.Spring, 1 => Season.Summer, 2 => Season.Autumn, 3 => Season.Winter, _ => Season.Spring }; } public int GetCurrentDayOfMonth() { // Calculate the current day of the year var dayOfYear = GetDaysPassed(); // 4 months per year // Calculate the current month var month = dayOfYear / daysPerMonth % monthsPerYear; return dayOfYear % daysPerMonth; } public int GetCurrentMonth() { // Calculate the current day of the year var dayOfYear = GetDaysPassed(); // 4 months per year // Calculate the current month return dayOfYear / daysPerMonth % monthsPerYear; } private string GetCurrentTime() { // Calculate the current hour and minute based on the time of day var timeOfDay = _currentTime / (dayLengthInMinutes * 60); var hours = Mathf.FloorToInt(timeOfDay * 24); var minutes = Mathf.FloorToInt((timeOfDay * 24 - hours) * 60); // Convert to 12-hour format and add AM/PM var hours12 = hours % 12; if (hours12 == 0) hours12 = 12; var amPm = hours < 12 ? "AM" : "PM"; return string.Format("{0:D2}:{1:D2} {2}", hours12, minutes, amPm); } public int GetDaysPassed() { return _daysPassed; } private IEnumerator DayNightCycleCoroutine() { var previousSeason = _currentSeason; while (true) { // Calculate the current time of day between 0 (midnight) and 1 (next midnight) var timeOfDay = _currentTime / (dayLengthInMinutes * 60); // Adjust the intensity of the light source based on the time of day globalLight.color = lightColorGradient.Evaluate(timeOfDay); globalLight.intensity = lightIntensityGradient.Evaluate(timeOfDay).a; // increment current time _currentTime += Time.deltaTime; // check if a day has passed if (_currentTime >= dayLengthInMinutes * 60) { _daysPassed++; Debug.Log("Day " + _daysPassed + " has passed"); _currentTime = 0; isFirstDay = false; OnDayChange?.Invoke(); var newSeason = GetCurrentSeason(); if (newSeason != previousSeason) { Debug.Log("Season changed from " + previousSeason + " to " + newSeason); previousSeason = newSeason; OnSeasonChange?.Invoke(); } } yield return null; } } }