167 lines
4.5 KiB
C#
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;
|
|
}
|
|
}
|
|
} |