C# Time Management (with Unity 2D) - c#

I ran into a little issue whilst using C#/Unity in combination with a litte countdown timer. The countdown is working fine an as expected, as long as the number of total timeToDisplay is not too big (e.g. more than a day)
r/Unity2D - Asking for Help: Countdown strangely stops when there is too much remaining time
As you can see, the user has the possibility to add time to that countdown, which (again) works fine, until it's too much.
Using TextMeshPro and TextMeshPro-Buttons.
Image of Countdown + Buttons to add Seconds/Minutes/Hours/Days
However... here's the code:
using UnityEngine;
using TMPro;
public class Controller : MonoBehaviour
{
public float timeValue = 78000;
public TMP_Text timerText;
// I also tried FixedUpdate, but error still occured
void Update()
{
if (timeValue > 0)
{
timeValue -= Time.deltaTime;
}
else
{
timeValue = 0;
}
DisplayTime(timeValue);
}
void DisplayTime(float timeToDisplay)
{
float days = Mathf.FloorToInt(timeToDisplay / 86400);
timeToDisplay = timeToDisplay % 86400;
float hours = Mathf.FloorToInt(timeToDisplay / 3600);
timeToDisplay = timeToDisplay % 3600;
float minutes = Mathf.FloorToInt(timeToDisplay / 60);
timeToDisplay = timeToDisplay % 60;
float seconds = Mathf.FloorToInt(timeToDisplay);
if (seconds < 0)
{
seconds = 0;
}
timerText.text = string.Format("{0:00} days {1:00} hours {2:00} minutes {3:00} seconds", days, hours, minutes, seconds);
}
public void AddDay()
{
/* 86400 seconds/day */
timeValue += 86400;
}
public void AddHour()
{
/* 3600 seconds/hour */
timeValue += 3600;
}
public void AddMinute()
{
timeValue += 60;
}
public void AddSecond()
{
timeValue += 1;
}
}
Does anybody know what I'm missing here?

problem on here: timeValue -= Time.deltaTime , float have a little deviation
public float timeValue = 78000;
float beginTime = 0;
void Start()
{
beginTime = Time.time;
}
// I also tried FixedUpdate, but error still occured
void Update()
{
float usedTime = Time.time - beginTime;
if( timeValue - usedTime > 0 )
{
DisplayTime(timeValue - usedTime);
}
else
{
DisplayTime(0);
}
}

Related

Unity - Trying to Calculate In-Game Time

So I wrote a day-night cycle script the other day and I have the sun/moon cycle working (its a really rough script, not perfect yet) but one of the other things I wanted to do was to be able to calculate the current time inside the game working off of that day/night cycle.
I have a ticker that is working so far but it is not scaling correctly to the percentage of the day.
Can anyone help me out with this because I think this is beyond my skillset with maths right now.
Basically I just want to solve the current time of day as relative to the % we are moving through the day/night cycle.
using System.Collections;
using System.Collections.Generic;
using System.Text;
using UnityEngine;
public class DayNightCycle : MonoBehaviour
{
public static DayNightCycle instance;
public Light sun, moon;
public float secondsInFullDay = 3600f;
[Range(0, 1)]
public float currentTimeOfDay = 0f;
[HideInInspector]
public float timeMultiplier = 1f;
float sunInitialIntensity;
public Camera mainCam;
public Material skyboxDay, skyBoxNight;
public float gameTime;
public float fSeconds;
public int totalSeconds, iSeconds, minutes, hours, days;
public int currentSecond, currentMinute, currentHour, currentDay;
public float previousTime;
private void Awake()
{
instance = this;
}
// Start is called before the first frame update
void Start()
{
sunInitialIntensity = sun.intensity;
}
// Update is called once per frame
void Update()
{
UpdateSun();
currentTimeOfDay += (Time.deltaTime / secondsInFullDay) * timeMultiplier;
if (currentTimeOfDay >= 1)
{
currentTimeOfDay = 0;
}
gameTime += Time.deltaTime;
// seconds / total seconds = percentage
// percentage * seconds = total seconds
// seconds = total seconds * percentage
totalSeconds = (int)gameTime;
fSeconds = (secondsInFullDay * currentTimeOfDay);
currentSecond = (int)fSeconds;
if (currentSecond >= 60)
IncrementMinutes();
if (currentMinute >= 60)
IncrementHours();
if (currentHour >= 24)
IncrementDays();
previousTime = (int)gameTime;
}
void UpdateSun()
{
sun.transform.localRotation = Quaternion.Euler((currentTimeOfDay * 360f) - 90, 170, 0);
moon.transform.localRotation = Quaternion.Euler((currentTimeOfDay * 360f) - 90, 170, 0);
float intensityMultiplier = 1f;
float moonIntensityMult = 0.025f;
if (currentTimeOfDay <= 0.23f || currentTimeOfDay >= 0.75f)
{
RenderSettings.skybox = skyBoxNight;
intensityMultiplier = 0f;
moonIntensityMult = 0.025f;
}
else if (currentTimeOfDay <= 0.25f)
{
RenderSettings.skybox = skyBoxNight;
intensityMultiplier = Mathf.Clamp01((currentTimeOfDay - 0.23f) * (1 / 0.02f));
moonIntensityMult = 0f;
}
else if (currentTimeOfDay >= 0.73f)
{
RenderSettings.skybox = skyboxDay;
intensityMultiplier = Mathf.Clamp01(1 - ((currentTimeOfDay - 0.73f) * (1 / 0.02f)));
moonIntensityMult = 0f;
}
sun.intensity = sunInitialIntensity * intensityMultiplier;
moon.intensity = moonIntensityMult;
}
public float GetTimeOfDayInSeconds
{
get { return currentTimeOfDay; }
set { return; }
}
void IncrementMinutes()
{
currentMinute++;
currentSecond = 0;
}
void IncrementHours()
{
currentHour++;
currentSecond = 0;
currentMinute = 0;
}
void IncrementDays()
{
currentDay++;
currentSecond = 0;
currentMinute = 0;
currentHour = 0;
}
}
I think keeping track of second, minute hour and increment each separtedly is not the right approach. You need to now the scale or proprotion factor between your game time and the real time, and handle the one time variable at once.
Find this trial function to obtain the sacaled time I think you need.
using System;
using UnityEngine;
public class DayNightCycle : MonoBehaviour {
// This is public to check with manual input if the obtained time is the one we expect.
// In the real method, this should not exist and should be calculated with the elapsed time of the game,
// commented belowin the getGameTime(int secodsDayDurationInGame) method
public double elapsedRealTime;
float startingGameTime;
DateTime startingGameDate;
private void Start() {
startingGameTime = Time.time;
startingGameDate = DateTime.Now; // choose the starting date you like
}
private float secondsOfARealDay = 24 * 60 * 60;
DateTime getGameTime(int secodsDayDurationInGame) {
float scaledElapsedSecondInGame = secondsOfARealDay / secodsDayDurationInGame; // second equivalent in your game
//float elapsedRealTime = Time.time - startingGameTime; // uncomment to calculate with elapsed real time.
DateTime gateDateTime = startingGameDate.AddSeconds(elapsedRealTime * scaledElapsedSecondInGame);
return gateDateTime;
}
void OnMouseDown() { // this makes the cube clickable
Debug.LogError(getGameTime(3600).ToString());
}
}
You can try it making a cube clickable to print the output when you update the elapsed time in the public variable.
It is for 3600 second day in your game, but if you whant another game day duration you can just make that variabel puclic and try.
Important to have a collider, if not, cube wont be clickable. However It is added by default when you add the primitive right click in the scene -> 3D Object -> Cube.
You can check for example that if you add 3600 to the elapsed time public variable, and you click the cube you obtain tomorrows date in the console.
When you check the function works according to your needs you can uncomment the line //float elapsedRealTime = Time.time - startingGameTime; to use the real time elapsed or the one you wish for the date calculation.
Okay so I got it to where it is correctly synched now with the day/night cycle I just need to clean this code up quite a bit. Note: The way I'm increasing days will start to fail if you use an exceptionally long in game day I think. The boolean might work but it might also give you a new day before the end of the current day. I was testing this on a 3600 second long day.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using UnityEngine;
public class DayNightCycle : MonoBehaviour
{
public static DayNightCycle instance;
public Light sun, moon;
public float secondsInFullDay = 3600f;
[Range(0, 1)]
public float currentTimeOfDay = 0f;
[HideInInspector]
public float timeMultiplier = 1f;
float sunInitialIntensity;
public Material skyboxDay, skyBoxNight;
public double elapsedRealTime;
public float secondsPerDayMultiplier;
[SerializeField]
private float speedOfGameSecond, speedOfGameMinute, speedOfGameHour, speedOfGameDay;
[SerializeField]
private float currentGameSecond, currentGameMinute, currentGameHour, currentGameDay;
private bool stopIncrementingDay;
private void Awake()
{
instance = this;
}
// Start is called before the first frame update
void Start()
{
speedOfGameSecond = secondsInFullDay / 24 / 60 / 60;
speedOfGameMinute = secondsInFullDay / 24 / 60;
speedOfGameHour = secondsInFullDay / 24;
speedOfGameDay = secondsInFullDay;
sunInitialIntensity = sun.intensity;
}
// Update is called once per frame
void Update()
{
UpdateSun();
currentTimeOfDay += (Time.deltaTime / secondsInFullDay) * timeMultiplier;
if (currentTimeOfDay >= 1)
{
currentTimeOfDay = 0;
}
secondsPerDayMultiplier = currentTimeOfDay * secondsInFullDay;
// seconds / total seconds = percentage
// percentage * seconds = total seconds
// seconds = total seconds * percentage
currentGameSecond = secondsPerDayMultiplier / speedOfGameSecond;
currentGameMinute = secondsPerDayMultiplier / speedOfGameMinute;
currentGameHour = secondsPerDayMultiplier / speedOfGameHour;
if(!stopIncrementingDay && currentGameHour >= 23.999)
{
IncrementDay();
stopIncrementingDay = true;
} else if(currentGameHour <= 23.999)
{
stopIncrementingDay = false;
}
elapsedRealTime += Time.deltaTime;
previousTime = Time.deltaTime;
}
void UpdateSun()
{
sun.transform.localRotation = Quaternion.Euler((currentTimeOfDay * 360f) - 90, 170, 0);
moon.transform.localRotation = Quaternion.Euler((currentTimeOfDay * 360f) - 90, 170, 0);
float intensityMultiplier = 1f;
float moonIntensityMult = 0.025f;
if (currentTimeOfDay <= 0.23f || currentTimeOfDay >= 0.85f)
{
RenderSettings.skybox = skyBoxNight;
intensityMultiplier = 0f;
moonIntensityMult = 0.025f;
}
else if (currentTimeOfDay <= 0.25f)
{
RenderSettings.skybox = skyBoxNight;
intensityMultiplier = Mathf.Clamp01((currentTimeOfDay - 0.23f) * (1 / 0.02f));
moonIntensityMult = 0f;
}
else if (currentTimeOfDay >= 0.83f)
{
RenderSettings.skybox = skyboxDay;
intensityMultiplier = Mathf.Clamp01(1 - ((currentTimeOfDay - 0.83f) * (1 / 0.02f)));
moonIntensityMult = 0f;
}
sun.intensity = sunInitialIntensity * intensityMultiplier;
moon.intensity = moonIntensityMult;
}
public float GetTimeOfDayPercent
{
get { return currentTimeOfDay; }
set { return; }
}
public float GetSecondsPerDay()
{
return secondsInFullDay;
}
private void IncrementDay()
{
currentGameSecond = 0;
currentGameMinute = 0;
currentGameHour = 0;
currentGameDay++;
}
public void GetTimeOfDay()
{
// now to work on this
}
}

Unity: How to transfer time script to 24 hours and not decimals

so I've found a script online for Unity that is a Day and Night cycle however it works in decimals, 0.1 to 1, however I want it to be 1 to 24.
The code I am using is below, I have tried fiddling around with the decimal values however I can't get it correct.
using UnityEngine;
using System.Collections;
public class DayNightCycle : MonoBehaviour {
public Light sun;
public float secondsInFullDay = 120f;
[Range(0,24)]
public float currentTimeOfDay = 0;
[HideInInspector]
public float timeMultiplier = 1f;
float sunInitialIntensity;
void Start() {
sunInitialIntensity = sun.intensity;
}
void Update() {
UpdateSun();
currentTimeOfDay += (Time.deltaTime / secondsInFullDay) * timeMultiplier;
if (currentTimeOfDay >= 24) {
currentTimeOfDay = 0;
}
}
void UpdateSun() {
sun.transform.localRotation = Quaternion.Euler((currentTimeOfDay * 360f) - 90, 170, 0);
float intensityMultiplier = 1;
if (currentTimeOfDay <= 0.23f || currentTimeOfDay >= 0.75f) {
intensityMultiplier = 0;
}
else if (currentTimeOfDay <= 0.25f) {
intensityMultiplier = Mathf.Clamp01((currentTimeOfDay - 0.23f) * (1 / 0.02f));
}
else if (currentTimeOfDay >= 0.73f) {
intensityMultiplier = Mathf.Clamp01(1 - ((currentTimeOfDay - 0.73f) * (1 / 0.02f)));
}
sun.intensity = sunInitialIntensity * intensityMultiplier;
}
}
The result I want is for the day and night cycle to work from 1 to 24 and not 0 to 1, so that there's 24 hours in the game, and that it's easier to modify when using a sleep script I've made.
To convert a value between 0 and 1 (interval [0, 1]) you just have to multiply by the size of your new interval then add the first value of your interval.
So if you have a variable value and want an interval: [MIN, MAX] the calculation is the following:
var newValue = (value * (MAX - MIN)) + MIN;
In you case you want the interval [1, 24] so it is:
var newValue = (value * 23) + 1;
Simple maths, hope it helps.

Created a duplicate text in same canvas but the second doesn't work

They have the exact same lines of code too but the second one doesn't work. The first countdown is supposed to run when the game first starts and the second whenever there's a battle going on.
Here's the first which works as intended:
public class Countdown : MonoBehaviour
{
float currentTime=0f;
float startingTime=5f;
public string outcome; //This will be the outcome of the random roll that will decide who attacks first
[SerializeField] Text countdownText;
void Awake()
{
currentTime = startingTime; //setting current time to 5
System.Random rand = new System.Random(); //choses a random number between 0 and 1
if (rand.Next(0, 2) == 0)
{
outcome = "Player 1 Attacks First";
}
else
{
outcome = "Player 2 Attacks First";
}
}
void Update()
{
if (currentTime > 3.5)
{
Timer();
countdownText.text = outcome; // Displays the player that starts attacking firtst
}
if (currentTime > 0.5&& currentTime<3.5) //Starts the timer from 3
{
Timer();
countdownText.text = currentTime.ToString("0");
}
if (currentTime < 0.5)
{
Timer();
countdownText.text = "GO";
}
if (currentTime < -0.5)
{
countdownText.text = "";
this.enabled = false;
}
}
void Timer()
{
currentTime -= 1 * Time.deltaTime;
}
}
And here's the second, it just displays "0":
public class CountdownInBattle : MonoBehaviour
{
float currentTime = 0f;
float startingTime = 5f;
[SerializeField] Text countdownText2;
// Start is called before the first frame update
void Awake()
{
currentTime = startingTime;
//if (GameObject.Find("Canvas").GetComponent<Countdown>().enabled == true)
//{
// this.enabled = false;
//}
Debug.Log("Starting Countdown");
}
// Update is called once per frame
void Update()
{
if (currentTime > 0.5 && currentTime < 3.5) //Starts the timer from 3
{
Timer();
countdownText2.text = currentTime.ToString("0");
}
if (currentTime < 0.5)
{
Timer();
countdownText2.text = "GO";
}
if (currentTime < -0.5)
{
countdownText2.text = "";
this.enabled = false;
}
}
void Timer()
{
currentTime -= 1 * Time.deltaTime;
}
}
This one is supposed to run every time there's a battle happening, but it doesn't work at all. Can't figure out why.
You set the currentTime to 5f at start.
So none of your conditions in Update
if (currentTime > 0.5 && currentTime < 3.5) //Starts the timer from 3
{
Timer();
countdownText2.text = currentTime.ToString("0");
}
if (currentTime < 0.5)
{
Timer();
countdownText2.text = "GO";
}
if (currentTime < -0.5)
{
countdownText2.text = "";
this.enabled = false;
}
ever matches -> nothing happens.
In the first script you had an additional condition for
if (currentTime > 3.5)
{
Timer();
countdownText.text = outcome; // Displays the player that starts attacking firtst
}
so quick fix would be to either increase that first condition to
if (currentTime > 0.5 && currentTime <= 5) //Starts the timer from 5
or to move the call of Timer(); outside of the conditions since it should be called every frame unconditional
I would strongly recommend to use a Coroutine for that so you can simply use the same component for both things:
public class Countdown : MonoBehaviour
{
[SerializeField] private Text _countdownText2;
public UnityEvent OnCountdownFinished;
public void StartCountdown(int forSeconds)
{
Debug.Log("Starting Countdown");
StartCoroutine(DoCountdown(forSeconds));
}
private IEnumerator DoCountdown(int forSeconds)
{
int seconds = forSeconds;
while (seconds > 0)
{
// yield means return to the main thread, render the frame
// and continue this method from this point
// in the next frame
// waitForSeconds does as it says ... repeat this return until X seconds have past
yield return new WaitForSeconds(1);
// reduce seconds by one
seconds--;
// update the text
_countdownText2.text = seconds.ToString();
}
// when done call the callbacks you added
OnCountdownFinished.Invoke();
}
}
OnCountdownFinished is a UnityEvent and works just like the onClick of buttons so you can simply execute any callback method when the countdown is finished.
and than add a callback either in the Inspector or you could set it all up from script like
public class FightController : MonoBehaviour
{
[SerialiteField] private int _secondsDisplayName;
[SerializeField] private int _secondsBeforeFight;
[SerializeField] private int _secondsInFight;
[SerializeField] private Countdown _beforeCountdown;
[SerializeField] private Countdown _inFightcountdown;
public string outcome;
private void Awake()
{
System.Random rand = new System.Random(); //choses a random number between 0 and 1
if (rand.Next(0, 2) == 0)
{
outcome = "Player 1 Attacks First";
}
else
{
outcome = "Player 2 Attacks First";
}
// and display the random outcome
// there is no need to update this every frame
countdownText.text = outcome;
}
private void Start()
{
// add a callback what should happen after the first countdown -> start the second
_beforeCountdown.OnCountdownFinished.AddListener(StartInFightCountdown);
// maybe also already add the callback what should happen after the second one
// Now since you want to display the random name for
// the first two seconds simply use a routine again:
StartCoroutine(Prepare());
}
private IEnumerator Prepare()
{
// wait the two seonds, than begin the before countdown at 3
yield return new WaitForSeconds(_secondsDisplayName);
// than start the first countdown
_beforeCountdown.StartCountdown(_secondsBeforeFight);
}
private void StartInFightCountdown()
{
_inFightcountdown.StartCountdown(_secondsInFight);
}
}

Unity Timer goes into negative?

So, I am trying to make a "Merchant" system for my game. After 5 minutes(timer is ticking) Merchant will be available and 2nd timer will start ticking, but the 2nd timer is in -.
void Update()
{
timeremaining -= Time.deltaTime;
int minutes = Mathf.FloorToInt(timeremaining / 60F);
int seconds = Mathf.FloorToInt(timeremaining - minutes * 60);
string niceTime = string.Format("{0:0}:{1:00}", minutes, seconds);
howlonghere -= Time.deltaTime;
int minutes2 = Mathf.FloorToInt(howlonghere / 60F);
int seconds2 = Mathf.FloorToInt(howlonghere - minutes * 60);
string niceTime2 = string.Format("{0:0}:{1:00}", minutes, seconds);
if (timeremaining > 0)
{
Merchanthuman.enabled = false;
Merchanthuman.interactable = false;
Tiimer.text = "Merchant will be here: " + niceTime;
}
else
{
Tiimer.text = "Merchant is here for: " + niceTime2;
Merchanthuman.enabled = true;
Merchanthuman.interactable = true;
}
}
That "Merchant is here for: " there should start new count down which would be 2nd time. Like the Will be here is 5 minutes & is here for is 2 minutes.
Let's split it up a little:
public const float TravelTime = 5.0f;
public const float VisitTime = 4.0f;
public float timeremaining;
public float howlonghere;
//Setup initial timers
void Start()
{
timeremaining = TravelTime;
howlonghere = VisitTime;
}
//Check each frame for the scenario
void Update()
{
if (timeremaining > 0)
{
string niceTime = ElapseTravel();
Merchanthuman.enabled = false;
Merchanthuman.interactable = false;
Tiimer.text = "Merchant will be here: " + niceTime;
}
else
{
string niceTime2 = ElapseVisit();
Tiimer.text = "Merchant is here for: " + niceTime2;
Merchanthuman.enabled = true;
Merchanthuman.interactable = true;
}
}
//Elapse remaining time when merchant travels
private string ElapseTravel()
{
timeremaining -= Time.deltaTime;
int minutes = Mathf.FloorToInt(timeremaining / 60F);
int seconds = Mathf.FloorToInt(timeremaining - minutes * 60);
return string.Format("{0:0}:{1:00}", minutes, seconds);
}
//Elapse stay time when merchant is here
private string ElapseVisit()
{
howlonghere -= Time.deltaTime;
int minutes2 = Mathf.FloorToInt(howlonghere / 60F);
int seconds2 = Mathf.FloorToInt(howlonghere - minutes2 * 60);
if (howlonghere <= 0)
{
timeremaining = TravelTime;
howlonghere = VisitTime;
}
return string.Format("{0:0}:{1:00}", minutes2, seconds2);
}
You were decreasing both timeremaining and howlonghere regardless of the situation. You need to split both scenarios and elapse (decrease) only one of the values depending on the fact that merchant is travelling to location or if he's already here.
Unity Timer is not negative. It is your own variable that is going negative.
What actually happening here is you are checking for 5 minutes and executing timeremaining -= Time.deltaTime; that will constantly decreasing your timeremaining variable.
Second thing is your are decreasing howlonghere at the same time by which it is going negative. Because howlonghere is less than timeremaining.
So when your first timer becomes timeremaining <= 0 then your second timer howlonghere will become howlonghere = -3 minutes. (Assuming that timeremaining = 5 and howlonghere = 2 initially).
What you can do if you don't want to change your logic here.
void Update()
{
timeremaining -= Time.deltaTime;
int minutes = Mathf.FloorToInt(timeremaining / 60F);
int seconds = Mathf.FloorToInt(timeremaining - minutes * 60);
string niceTime = string.Format("{0:0}:{1:00}", minutes, seconds);
if (timeremaining > 0)
{
Merchanthuman.enabled = false;
Merchanthuman.interactable = false;
Tiimer.text = "Merchant will be here: " + niceTime;
}
else {
howlonghere -= Time.deltaTime;
int minutes2 = Mathf.FloorToInt(howlonghere / 60F);
int seconds2 = Mathf.FloorToInt(howlonghere - minutes * 60);
string niceTime2 = string.Format("{0:0}:{1:00}", minutes, seconds);
Tiimer.text = "Merchant is here for: " + niceTime2;
Merchanthuman.enabled = true;
Merchanthuman.interactable = true;
}
}
Obviously you will customize it more accordingly. But it is just to make you clear.

Time.time make my Color Lerp not 'lerp'

I'm making a day/night cycle and have the lerp on Time.time, because if I use Time.deltaTime it turns night.day around so its day at 12am. However I digress.
The problem I'm running into now too is that with any Time setting it will make the lerp instant and not - well.. 'lerp'. Any idea on fixing this? I'm a C# newbie
I got it working with this as the time script:
using UnityEngine;
using System.Collections;
public class timeFlow : MonoBehaviour
{
public float Hours = 00;
public float Minutes = 00;
void Update()
{
if(Hours <= 23){
if(Minutes >= 60)
{
Minutes = 0;
if(Minutes <= 59)
{
Hours++;
}
else
{
Minutes = 0;
Hours = 0;
guiText.text = Hours.ToString("f0") + ":0" + Minutes.ToString("f0");
}
}
else
{
Minutes += UnityEngine.Time.deltaTime * 100;
}
if(Mathf.Round(Minutes) <= 9)
{
guiText.text = Hours.ToString("f0") + ":0" + Minutes.ToString("f0");
}
else
{
guiText.text = Hours.ToString("f0") + ":" + Minutes.ToString("f0");
}
}
else {
Hours = 0;
}
}
}
And this is the lerp script:
using UnityEngine;
using System.Collections;
public class cycleFlow : MonoBehaviour {
public Color32 night = new Color32(30, 30, 30, 255);
public Color32 day = new Color32(255, 255, 255, 255);
public GameObject Timer;
private timeFlow TimeFlow;
void Awake () {
TimeFlow = Timer.GetComponent<timeFlow> ();
}
void Update () {
DayNightCycle ();
}
void DayNightCycle()
{
foreach (SpriteRenderer child in transform.GetComponentsInChildren<SpriteRenderer>()) {
if (TimeFlow.Hours == 18){
child.color = Color.Lerp(day, night, Time.time);
}
if (TimeFlow.Hours == 6) {
child.color = Color.Lerp(night, day, Time.time);
}
}
}
}
You can write something like this, Lerp takes actual (from) value, final (to) value and fraction value. (here Time.deltaTime) Now when your timer will reach hour 18, your Color will change to color of night in few Update function calls (you can control change time by multiplying Time.deltaTime) :)
foreach ( SpriteRenderer child in transform.GetComponentsInChildren<SpriteRenderer>() ) {
if ( TimeFlow.Hours == 18 ) {
child.color = Color.Lerp(child.color, night, Time.deltaTime);
// here two times faster
// child.color = Color.Lerp(child.color, night, Time.deltaTime * 2.0f);
}
if ( TimeFlow.Hours == 6 ) {
child.color = Color.Lerp(child.color, day, Time.deltaTime);
// here half slower :)
// child.color = Color.Lerp(child.color, night, Time.deltaTime * 0.5f);
}
}
I had a hard time understanding lerp when used together with a time.
Maybe this example helps someone:
// lerp values between 0 and 10 in a duration of 3 seconds:
private float minValue = 0.0f;
private float maxValue = 10.0f;
private float totalDuration = 3.0f;
private float timePassed = 0.0f;
private float currentValue;
void Update()
{
timePassed += Time.deltaTime;
// Lerp expects a value between 0 and 1 as the third parameter,
// so we need to divide by the duration:
currentValue = Mathf.Lerp(minValue, maxValue, timePassed/totalDuration);
}
Note: you need to add some logic for:
handling when to start/stop lerping
when to reset timePassed

Categories