I’m trying to create a Time of Day script, using Unity 5. Is there a way to calculate the actual time of day with the values that fCurrentTimeOfDay gives (a float between 0.0 - 1.0) - 0.0 being 00:00 and 1.0 being 23:59…
Here’s the script:
using UnityEngine;
using System.Collections;
public class TOD_Base : MonoBehaviour {
public Light lSun;
public float fSecondsDefaultDay;
[Range(0, 1)]
public float fCurrentTimeOfDay = 0.0f;
[HideInInspector]
public float fTimeMultiplier = 1.0f;
private float fSunStartIntensity;
public int currentDay = 1;
public int currentMonth = 5;
public int currentYear = 2015;
void Start()
{
fSunStartIntensity = lSun.intensity;
}
void Update()
{
UpdateSun();
// Control the speed of our "clock"
fCurrentTimeOfDay += (Time.deltaTime / fSecondsDefaultDay) * fTimeMultiplier;
// Resets our time of day to 0
if (fCurrentTimeOfDay >= 1)
{
fCurrentTimeOfDay = 0;
currentDay += 1;
if(currentDay == 32)
{
currentDay = 1;
currentMonth += 1;
if(currentMonth == 13)
{
currentMonth = 1;
currentYear += 1;
currentDay = 1;
}
}
Debug.Log("Current date: " + currentDay + "/" + currentMonth + "/" + currentYear);
}
}
void UpdateSun()
{
// Rotate the sun 360 degress in X-axis according to our current time of day
lSun.transform.localRotation = Quaternion.Euler((fCurrentTimeOfDay * 360) - 90f, 170, 0);
// Set the sun to full intesity during the day
float fIntensityMultiplier = 1.0f;
if (fCurrentTimeOfDay <= 0.23f || fCurrentTimeOfDay >= 0.75f)
{
fIntensityMultiplier = 0.0f;
}
else if (fCurrentTimeOfDay <= 0.25f)
{
fIntensityMultiplier = Mathf.Clamp01((fCurrentTimeOfDay - 0.23f) * (1 / 0.02f));
}
else if (fCurrentTimeOfDay >= 0.75f)
{
fIntensityMultiplier = Mathf.Clamp01(1 - ((fCurrentTimeOfDay - 0.73f) * (1 / 0.02f)));
}
// Multuply the intensity of the sun according to the time of day
lSun.intensity = fSunStartIntensity * fIntensityMultiplier;
}
}
if you’re only going to “minute” accuracy, there are 1440 minutes in a 24 hour period, your normalised value times by that will give you the current time in “minutes”, then you just need to format that into hours/minutes.
In the inspector I set the time to start the scene at setting the normalised value, I’ve created two public ints (tHour and tMinute) - maybe a Vector2-solution is better(?). Is there a way to convert tHour and tMinute to a normalized value? It’s kind of a pain in the a… to try to set the correct time using the normalised value…
I have NO IDEA how to convert stringTime to normalised float. Been googling until my fingers hurt how to convert strings to normalised floats but not with the result I was hoping for… I don’t know how much of a difference it makes that the designer can type either “00:45” or “00:45:31” into stringTime in the inspector, but not only hours…
I want fCurrentTimeOfDay to equal the normalised float value of the string stringTime…
Don’t know if I implemented it wrong or not, but I couldn’t get it to work…
It seems that only adjusting the fCurrentTimeOfDay changes the stringTime to the correct time, but not the other way around. If I type “14:30” or “14:30:00” into stringTime in the inspector, fCurrentTimeOfDay stays unchanged… and when the game starts the time starts at “00:00:00” no matter what I set it to in the inspector.
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
using System;
[ExecuteInEditMode]
public class TOD_Base : MonoBehaviour {
private Player_Base plBase;
[Header("UI")]
public Text timeTextUI;
public Text dateTextUI;
public Text seasonTextUI;
[Header("Seasons")]
[SerializeField] private string seasonSpring = "Spring";
[SerializeField] private string seasonSummer = "Summer";
[SerializeField] private string seasonAutumn = "Autumn";
[SerializeField] private string seasonWinter = "Winter";
[Header("Ambient Settings")]
// This will change the ambient light depending on the time of day
public Gradient ambientLight;
public AnimationCurve ambientIntensity;
[Header("TOD Settings")]
public Light lSun;
public float fSecondsDefaultDay;
[Space(5)]
[Range(0, 1)] public float fCurrentTimeOfDay;
public string stringTime = "14:30";
[HideInInspector]
public float fTimeMultiplier = 1.0f;
public float fSunStartIntensity;
public int currentDay = 1;
public int currentMonth = 5;
public int currentYear = 2015;
private int hours;
private int minutes;
private int seconds;
void Start()
{
plBase = (Player_Base)FindObjectOfType<Player_Base>();
lSun.intensity = fSunStartIntensity;
TimeSpan timeSpan = TimeSpan.FromDays(fCurrentTimeOfDay);
stringTime = timeSpan.ToString();
Debug.Log("fCurrentTimeOfDay: " + fCurrentTimeOfDay);
Debug.Log("TIME: " + stringTime);
Debug.Log("Map: " + Map(fCurrentTimeOfDay, 0, 1, 0, 24));
var split = stringTime.Split(':');
hours = Int32.Parse(split[0]);
minutes = Int32.Parse(split[1]);
float roundedSeconds = float.Parse(split[2].Replace('.', ','));
seconds = (int)Math.Round(roundedSeconds);
fCurrentTimeOfDay = Map(hours * 60 + minutes + seconds / 60f, 0, 1440, 0, 1);
Debug.Log("Hours: " + hours);
Debug.Log("Minutes: " + minutes);
Debug.Log("Seconds: " + seconds);
Debug.Log("Total minutes: " + (hours * 60 + minutes + seconds / 60f));
Debug.Log("Map: " + Map(hours * 60 + minutes + seconds / 60.0f, 0, 1440, 0, 1));
}
void Update()
{
TimeSpan timeSpan = TimeSpan.FromDays(fCurrentTimeOfDay);
fCurrentTimeOfDay += (Time.deltaTime / fSecondsDefaultDay) * fTimeMultiplier;
stringTime = Map(hours * 60 + minutes + fSecondsDefaultDay / 60f, 0, 1440, 0, 1).ToString();
stringTime = timeSpan.ToString();
SetAmbientLight(fCurrentTimeOfDay);
// Calculate actual time of day in HH:mm:ss for the HUD
float sec;
sec = fCurrentTimeOfDay * fSecondsDefaultDay;
timeSpan = TimeSpan.FromSeconds(sec);
string timeText = string.Format("{0:smile:2}:{1:smile:2}:{2:smile:2}", timeSpan.Hours, timeSpan.Minutes, timeSpan.Seconds);
timeTextUI.text = timeText;
// Resets our time of day to 0
if (fCurrentTimeOfDay >= 1)
{
fCurrentTimeOfDay = 0;
currentDay += 1;
if(currentDay == 32)
{
currentDay = 1;
currentMonth += 1;
if(currentMonth == 13)
{
currentMonth = 1;
currentYear += 1;
currentDay = 1;
}
}
}
dateTextUI.text = currentDay + "/" + currentMonth + "/" + currentYear;
// Set current season
if(currentMonth >= 10 && currentMonth <= 12)
{
seasonTextUI.text = seasonWinter;
} else if(currentMonth >= 8 && currentMonth <= 10)
{
seasonTextUI.text = seasonAutumn;
} else if(currentMonth >= 5 && currentMonth <= 8)
{
seasonTextUI.text = seasonSummer;
} else if(currentMonth >= 2 && currentMonth <= 5)
{
seasonTextUI.text = seasonSpring;
} else
{
seasonTextUI.text = seasonWinter;
}
UpdateSun();
}
public static float Map(float value, float leftMin, float leftMax, float rightMin, float rightMax)
{
return rightMin + (value - leftMin) * (rightMax - rightMin) / (leftMax - leftMin);
}
void UpdateSun()
{
// Rotate the sun 360 degress in X-axis according to our current time of day
lSun.transform.localRotation = Quaternion.Euler((fCurrentTimeOfDay * 360) - 90f, 130, 0);
// Set the sun to full intesity during the day
float fIntensityMultiplier = 1.0f;
if (fCurrentTimeOfDay <= 0.23f || fCurrentTimeOfDay >= 0.75f)
{
fIntensityMultiplier = 0.0f;
}
else if (fCurrentTimeOfDay <= 0.25f)
{
fIntensityMultiplier = Mathf.Clamp01((fCurrentTimeOfDay - 0.23f) * (1 / 0.02f));
}
else if (fCurrentTimeOfDay >= 0.75f)
{
fIntensityMultiplier = Mathf.Clamp01(1 - ((fCurrentTimeOfDay - 0.73f) * (1 / 0.02f)));
}
// Multiply the intensity of the sun according to the time of day
lSun.intensity = fSunStartIntensity * fIntensityMultiplier;
}
void SetAmbientLight(float _currentTime)
{
RenderSettings.ambientLight = ambientLight.Evaluate(_currentTime);
RenderSettings.ambientIntensity = ambientIntensity.Evaluate(_currentTime);
lSun.color = ambientLight.Evaluate(_currentTime);
}
}
public class NewBehaviourScript : MonoBehaviour
{
public enum ParameterType
{
FLOAT,
STRING
}
public ParameterType Type;
[Range(0, 1)]
public float fCurrentTimeOfDay;
public string stringTime = "14:30";
void Start()
{
switch (Type)
{
case ParameterType.FLOAT:
// if you want use float to know stringTime use:
stringTime = FloatToTime(fCurrentTimeOfDay);
break;
case ParameterType.STRING:
// if you want use stringTime to know float use
fCurrentTimeOfDay = TimeToFloat(stringTime);
break;
}
}
// to check in real time
void Update()
{
switch (Type)
{
case ParameterType.FLOAT:
// if you want use float to know stringTime use:
stringTime = FloatToTime(fCurrentTimeOfDay);
break;
case ParameterType.STRING:
// if you want use stringTime to know float use
fCurrentTimeOfDay = TimeToFloat(stringTime);
break;
}
}
/// <summary>
/// maps value (which is in the range leftMin - leftMax) to a value in the range rightMin - rightMax
/// </summary>
/// <param name="value">Value.</param>
/// <param name="leftMin">Left minimum.</param>
/// <param name="leftMax">Left max.</param>
/// <param name="rightMin">Right minimum.</param>
/// <param name="rightMax">Right max.</param>
public static float Map(float value, float leftMin, float leftMax, float rightMin, float rightMax)
{
return rightMin + (value - leftMin) * (rightMax - rightMin) / (leftMax - leftMin);
}
public float TimeToFloat(string time)
{
// "11:12:13" became ["11","12","13"] or "11:12" became ["11","12"]
var split = time.Split(':');
float temp = 60;
// total minutes
float minutes = 0;
// first stringPart value is hours, second - minutes, third - seconds
int i = 0;
foreach (var stringPart in split)
{
// "11.12" became 13.12f or "11" became 11.0f
float value = float.Parse(stringPart, CultureInfo.InvariantCulture);
// 13.12f became 13 or 13.66f became 14
int roundedValue = (int)Math.Round(value);
// if stringPart = hours, we should MULTIPLY this value by 60 to get minutes
// if stringPart = minutes
// if stringPart = seconds, we should DIVIDE this value by 60 to get minutes
minutes += roundedValue * temp;
// first time this value = 60(hours), then 1(minutes), and then 1/60(seconds)
temp /= 60.0f;
}
// then we map current minutes value, if total minutes = 720, then our float value = 0.5f
return Map(minutes, 0, 1440, 0, 1);
}
public string FloatToTime(float time)
{
TimeSpan timeSpan = TimeSpan.FromDays(fCurrentTimeOfDay);
if (fCurrentTimeOfDay == 1)
return "24:00:00";
return string.Format("{0:g}", timeSpan);
}
}