SanAndreasUnity/Assets/Scripts/Behaviours/World/DayTimeManager.cs

184 lines
6.3 KiB
C#
Raw Normal View History

2021-05-03 02:59:57 +02:00
using SanAndreasUnity.Utilities;
using UnityEngine;
2020-05-31 19:07:22 +02:00
namespace SanAndreasUnity.Behaviours.World
{
2022-01-23 03:55:53 +01:00
public class DayTimeManager : Utilities.SingletonComponent<DayTimeManager>
2020-05-31 19:07:22 +02:00
{
2021-05-02 23:01:31 +02:00
public AnimationCurve lightAngleCurve;
public AnimationCurve lightIntensityCurve;
public AnimationCurve nightColorsIntensityCurve;
2020-05-31 19:07:22 +02:00
2021-05-02 23:01:31 +02:00
public Light directionalLight;
2020-05-31 19:07:22 +02:00
2021-07-18 21:05:39 +02:00
public float lightYAngle = 45f;
2021-05-02 23:01:31 +02:00
public byte startTimeHours = 12;
public byte startTimeMinutes = 0;
2020-05-31 19:07:22 +02:00
2021-05-02 23:01:31 +02:00
public byte CurrentTimeHours { get; private set; }
public byte CurrentTimeMinutes { get; private set; }
2020-05-31 19:07:22 +02:00
2021-05-03 01:55:41 +02:00
public float CurrentCurveTime => (this.CurrentTimeHours + this.CurrentTimeMinutes / 60f) / 24f;
public float CurrentCurveTimeStepped => this.CurrentTimeHours / 24f;
2021-05-04 20:55:01 +02:00
public string CurrentTimeAsString => FormatTime(this.CurrentTimeHours, this.CurrentTimeMinutes);
2021-05-02 23:01:31 +02:00
private float m_timeSinceTimeAdvanced = 0;
2021-04-26 00:43:30 +02:00
2021-06-25 18:56:52 +02:00
public float TimeWhenTimeWasSet { get; private set; } = 0;
public float TimeSinceTimeWasSet => Time.time - this.TimeWhenTimeWasSet;
2021-05-02 23:01:31 +02:00
public float timeScale = 1;
2021-04-26 00:43:30 +02:00
2021-05-02 23:01:31 +02:00
public float nightColorsMultiplier = 0.1f;
2020-05-31 19:07:22 +02:00
2021-05-02 23:01:31 +02:00
private float m_originalSkyboxExposure;
2020-05-31 19:07:22 +02:00
2021-05-02 23:01:31 +02:00
public bool controlLightIntensity = true;
public bool disableLightDuringNight = true;
public Color moonColor = Color.blue;
private Color m_originalLightColor;
2021-05-03 00:17:08 +02:00
private static int s_exposurePropertyId = -1;
public static int ExposurePropertyId => s_exposurePropertyId == -1 ? s_exposurePropertyId = Shader.PropertyToID("_Exposure") : s_exposurePropertyId;
private static int s_nightMultiplierPropertyId = -1;
public static int NightMultiplierPropertyId => s_nightMultiplierPropertyId == -1 ? s_nightMultiplierPropertyId = Shader.PropertyToID("_NightMultiplier") : s_nightMultiplierPropertyId;
2021-05-03 02:59:57 +02:00
public event System.Action onTimeChanged = delegate {};
public event System.Action onHourChanged = delegate {};
2021-05-03 02:59:57 +02:00
2021-05-02 23:01:31 +02:00
2022-01-26 21:25:33 +01:00
#if UNITY_EDITOR
[UnityEditor.InitializeOnLoadMethod]
static void InitOnLoad()
{
if (null == Singleton)
return;
Singleton.Init();
}
#endif
2022-01-23 03:55:53 +01:00
protected override void OnSingletonAwake()
2022-01-26 21:25:33 +01:00
{
this.Init();
}
void Init()
2020-05-31 19:07:22 +02:00
{
2021-05-02 23:01:31 +02:00
m_originalLightColor = this.directionalLight.color;
2021-05-03 00:17:08 +02:00
m_originalSkyboxExposure = RenderSettings.skybox.GetFloat(ExposurePropertyId);
2020-05-31 19:07:22 +02:00
}
2022-01-23 03:55:53 +01:00
protected override void OnSingletonDisable()
2020-05-31 19:07:22 +02:00
{
2021-05-02 23:01:31 +02:00
// restore material settings
if (Application.isEditor)
2021-05-03 00:17:08 +02:00
RenderSettings.skybox.SetFloat(ExposurePropertyId, m_originalSkyboxExposure);
2020-05-31 19:07:22 +02:00
}
2022-01-23 03:55:53 +01:00
protected override void OnSingletonStart()
2020-05-31 19:07:22 +02:00
{
2021-05-03 04:18:59 +02:00
if (NetUtils.IsServer)
this.SetTime(this.startTimeHours, this.startTimeMinutes, false);
2021-04-26 00:43:30 +02:00
}
2021-05-02 23:01:31 +02:00
private void Update()
2021-04-26 00:43:30 +02:00
{
2021-05-02 23:01:31 +02:00
m_timeSinceTimeAdvanced += Time.deltaTime * this.timeScale;
2021-04-26 00:43:30 +02:00
2021-05-03 04:18:59 +02:00
if (m_timeSinceTimeAdvanced >= 1 && NetUtils.IsServer)
2021-05-02 23:01:31 +02:00
{
m_timeSinceTimeAdvanced = 0;
this.AdvanceTime();
2021-04-26 00:43:30 +02:00
}
2020-05-31 19:07:22 +02:00
}
2021-05-02 23:01:31 +02:00
void AdvanceTime()
2020-05-31 19:07:22 +02:00
{
2021-05-02 23:01:31 +02:00
int newHours = this.CurrentTimeHours;
int newMinutes = this.CurrentTimeMinutes + 1;
if (newMinutes >= 60)
2020-05-31 19:07:22 +02:00
{
2021-05-02 23:01:31 +02:00
newMinutes = 0;
2020-05-31 19:07:22 +02:00
2021-05-02 23:01:31 +02:00
newHours++;
if (newHours >= 24)
newHours = 0;
2020-05-31 19:07:22 +02:00
}
2021-05-02 23:01:31 +02:00
this.SetTime((byte) newHours, (byte) newMinutes, false);
2020-05-31 19:07:22 +02:00
}
2021-05-02 23:01:31 +02:00
public void SetTime(byte hours, byte minutes, bool log)
2020-05-31 19:07:22 +02:00
{
2021-05-02 23:01:31 +02:00
hours = (byte) Mathf.Clamp(hours, 0, 23);
minutes = (byte) Mathf.Clamp(minutes, 0, 59);
2020-05-31 19:07:22 +02:00
byte oldHour = this.CurrentTimeHours;
2021-05-02 23:01:31 +02:00
this.CurrentTimeHours = hours;
this.CurrentTimeMinutes = minutes;
2020-05-31 19:07:22 +02:00
2021-05-03 04:18:59 +02:00
m_timeSinceTimeAdvanced = 0;
2021-06-25 18:56:52 +02:00
this.TimeWhenTimeWasSet = Time.time;
2021-05-03 04:18:59 +02:00
float curveTime = this.CurrentCurveTimeStepped;
2020-05-31 19:07:22 +02:00
2021-05-02 23:01:31 +02:00
float lightIntensity = this.lightIntensityCurve.Evaluate(curveTime);
bool isNight = lightIntensity <= 0;
if (this.controlLightIntensity)
this.directionalLight.intensity = Mathf.Abs(lightIntensity);
if (this.disableLightDuringNight)
this.directionalLight.enabled = !isNight;
else
{
this.directionalLight.enabled = true;
this.directionalLight.color = isNight ? this.moonColor : m_originalLightColor;
2020-05-31 19:07:22 +02:00
}
2021-05-02 23:01:31 +02:00
float skyboxExposure = isNight ? 0f : m_originalSkyboxExposure * lightIntensity;
2021-05-03 00:17:08 +02:00
RenderSettings.skybox.SetFloat(ExposurePropertyId, skyboxExposure);
2020-05-31 19:07:22 +02:00
2021-05-03 01:55:41 +02:00
float lightAngle = this.UpdateLightAngle(curveTime);
2021-05-02 23:01:31 +02:00
float nightMultiplier = this.nightColorsIntensityCurve.Evaluate(curveTime) * this.nightColorsMultiplier;
2021-05-03 00:17:08 +02:00
Shader.SetGlobalFloat(NightMultiplierPropertyId, nightMultiplier);
2020-05-31 19:07:22 +02:00
2021-05-02 23:01:31 +02:00
if (log)
{
Debug.Log($"Time set to {hours}:{minutes}, curveTime {curveTime}, lightIntensity {lightIntensity}, lightAngle {lightAngle}, nightMultiplier {nightMultiplier}");
}
2021-05-03 02:59:57 +02:00
F.InvokeEventExceptionSafe(this.onTimeChanged);
if (oldHour != this.CurrentTimeHours)
F.InvokeEventExceptionSafe(this.onHourChanged);
2020-05-31 19:07:22 +02:00
}
2021-05-03 01:55:41 +02:00
float UpdateLightAngle(float curveTime)
{
float lightAngle = this.lightAngleCurve.Evaluate(curveTime) * 180f;
2021-07-18 21:05:39 +02:00
this.directionalLight.transform.rotation =
Quaternion.AngleAxis(lightAngle, Vector3.right) * Quaternion.AngleAxis(this.lightYAngle, Vector3.up);
2021-05-03 01:55:41 +02:00
return lightAngle;
}
2021-05-03 02:59:57 +02:00
public static void CurveTimeToHoursAndMinutes(float curveTime, out byte hours, out byte minutes)
{
2021-05-03 04:18:59 +02:00
float hoursWithMinutes = curveTime * 24f;
hours = (byte) Mathf.FloorToInt(hoursWithMinutes);
float hourPerc = hoursWithMinutes - Mathf.Floor(hoursWithMinutes);
minutes = (byte) Mathf.RoundToInt(60 * hourPerc);
2021-05-03 02:59:57 +02:00
}
2021-05-04 20:55:01 +02:00
public static string FormatTime(byte hours, byte minutes)
{
return $"{hours:00}:{minutes:00}";
}
2020-05-31 19:07:22 +02:00
}
}