evershade/Assets/Scripts/Managers/DayNightCycleManager.cs

167 lines
4.5 KiB
C#

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