- Home /
Accelerate/Decelerate Custom Game Clock
I created a game clock to have an ingame reference to time, plus, to have a variable defining certain events (like day/night cycle, temperature, seasons, etc.).
It works fine when I set the "timespeedmultiplier" and then hit start to simulate the game. It has to be set to the quantity of seconds that passes in one real second. So if "timespeedmult." is set at 60, each game minute passes every real second.
The problem comes when I created buttons on the GUI(custom planes with raycast) to be able to change the speed of the game while it's running. What happens is the time just shifts massively.
Example; if it goes realtime (1 sec = 1 sec) and I switch "timespeedmultiplier" to 60 (1 minute = 1 sec) instead of just speeding up from the actual time, it adds time and then goes quicker. So the problem is that "adding time" thing, I dont know why it happens. If it's minute 5 and hour 2, it jumps to (I don't exactly know) 30 minutes and 6 hours, which, obviously, I don't want to happen.
Here the code(I skipped the non-time related code); Its C#.
///VARIABLES///
public double timeSpeedMultiplier; ///set in inspector then switched ingame
private double realSECOND = 0;
private const double SECONDinSeconds = 1;
private const double MINUTEinSeconds = SECONDinSeconds * 60;
private const double HOURinSeconds = MINUTEinSeconds * 60;
private const double DAYinSeconds = HOURinSeconds * 24;
private const double MONTHinSeconds = DAYinSeconds * (365/12);
private const double YEARinSeconds = MONTHinSeconds * 12;
///UPDATE()///
realSECOND += Time.deltaTime; ///Real seconds
SECOND = realSECOND * timeSpeedMultiplier; ///Game seconds
MINUTE = (SECOND/MINUTEinSeconds);
HOUR = ((MINUTE*MINUTEinSeconds)/HOURinSeconds);
DAY = ((HOUR*HOURinSeconds)/DAYinSeconds);
MONTH = ((DAY*DAYinSeconds)/MONTHinSeconds);
YEAR = ((MONTH*MONTHinSeconds)/YEARinSeconds);
Thanks in advance.
Answer by SuIXo3 · Jul 27, 2012 at 11:13 PM
I finally got it! I rewrote the whole thing. This code should actually work copy/pasting for those interested. 1,2,3,4 and 5 keys are to change time speed, and it's displayed with OnGUI function.
The useful variable here is "totalGameSeconds", which is the time in seconds that has passed since startup taking in account the user speed choices.
using UnityEngine;
using System.Collections;
public class GameTimer : MonoBehaviour {
public double totalGameSeconds;
public double seconds;
public double minutes;
public double hours;
public double days;
public double months;
public double years;
private double secondsPerSecond;
void Start () {
secondsPerSecond = 1;
totalGameSeconds += secondsPerSecond * Time.deltaTime;
}
void Update () {
if( Input.GetKeyDown(KeyCode.Alpha1)){
secondsPerSecond = 1;
}
else if( Input.GetKeyDown(KeyCode.Alpha2)){
secondsPerSecond = 60;
}
else if( Input.GetKeyDown(KeyCode.Alpha3)){
secondsPerSecond = 3600;
}
else if( Input.GetKeyDown(KeyCode.Alpha4)){
secondsPerSecond = 86400;
}
else if( Input.GetKeyDown(KeyCode.Alpha5)){
secondsPerSecond = 2629743;
}
totalGameSeconds += secondsPerSecond * Time.deltaTime;
seconds = totalGameSeconds;
minutes = totalGameSeconds / 60;
hours = minutes / 60;
days = hours / 24;
months = days / (365/12);
years = months / 12;
}
void OnGUI(){
GUI.Label(new Rect(0,200, 500, 500), "Total Seconds: " + totalGameSeconds);
GUI.Label(new Rect(0,225, 500, 500), "Seconds Per Second: " + secondsPerSecond);
GUI.Label(new Rect(0,250, 500, 500), "Second: " + (int)seconds%60);
GUI.Label(new Rect(0,275, 500, 500), "Minute: " + (int)minutes%60);
GUI.Label(new Rect(0,300, 500, 500), "Hour: " + (int)hours%24);
GUI.Label(new Rect(0,325, 500, 500), "Day: " + (int)days%(365/12));
GUI.Label(new Rect(0,350, 500, 500), "Month: " + (int)months%12);
GUI.Label(new Rect(0,375, 500, 500), "Year: " + (int)years);
}
}
Thanks for co$$anonymous$$g back to give your solution. I implemented this in my project and it works great, truly appreciated!
Answer by Seth-Bergman · Jul 25, 2012 at 02:16 PM
once you change : SECONDinSeconds = 1;
you need to update all this:
MINUTEinSeconds = SECONDinSeconds * 60;
HOURinSeconds = MINUTEinSeconds * 60;
DAYinSeconds = HOURinSeconds * 24;
MONTHinSeconds = DAYinSeconds * (365/12);
YEARinSeconds = MONTHinSeconds * 12;
so add all that to a method, and call it whenever SECONDinSeconds changes
EDIT: actually I take that back ... I think just get rid of the extra multiplication, use this:
SECOND = realSECOND * timeSpeedMultiplier; ///Game seconds
MINUTE = (SECOND/MINUTEinSeconds);
HOUR = (MINUTE/HOURinSeconds);
DAY = (HOUR/DAYinSeconds);
MONTH = (DAY/MONTHinSeconds);
YEAR = (MONTH/YEARinSeconds);
no need to multiply it all again, that was the prob :)
$$anonymous$$hm, yes that seems to do the trick, I haven't thought of it. Thanks!. But I should change the "const" so I can alter the variable. But so now ins$$anonymous$$d of changing the value to 60, 3600, etc. It should be 1 for real time and 0.5 for half real time, right? If it works it's nice but I'll have to calculate the relations. $$anonymous$$y objective is speeding up time by choosing which element you want to pass each second.
So the thing would be to create a function with the code I have and call it with a certain value inside the Update function. That value being the time speed you choose. I think I got it. I'll try it out when I'm on it.
Thanks again.
Seems to easy xD. I'll try that last and if nothing I'll try the first. Thanks!
Well it seemed to easy :P Both solutions didn't work. The last one, deleting the multiplication, somehow disables the clock, and messes up the time, like hours don't pass as hours anymore.
And the first, changing the SECONDinseconds, kind of works, but simulated. I mean, if I input 0.5, time doesn't passes twice as fast, it's just that to make one $$anonymous$$ute you need only 30 secs, not 60. It's kind of weird.
But I did noticed something! I have a real seconds counter, counting each second passed since the beginning of the simulation, real time. And I saw that when I accelerate time, the element I chose to be going at one unit per second gets from the number it was to the number the real seconds are. If $$anonymous$$utes is 5, and real seconds is 345 (example), if from realtime I switch to go at one $$anonymous$$ute per second, $$anonymous$$utes jump from 5 to 345 and then accelerate. I don't know if it's well explained xD.
$$anonymous$$aybe I should blend our ideas. $$anonymous$$ine about the "timespeedmultiplier", which works when left alone. And yours about the specialized function to which I give the timespeedmult. value calling it from Update(). I have 5 different time speeds, realtime, $$anonymous$$ per sec, hour per sec, day per sec and month per sec. So I would need to give those 5 values to the same function depending on which GUI button I click. But now I'm thinking it's gonna make the same mistake, just add a number of secs, then speed up.
$$anonymous$$aybe if each time I change the speed I take from the realseconds variable the same amount that the timespeemultiplier gives? It should prevent the sum it makes all the time and start where it was before clicking.
$$anonymous$$y head hurts xD
Your answer
Follow this Question
Related Questions
how to slow down speed increase? 2 Answers
Multiple Cars not working 1 Answer
Couldn't resume once Time.timeScale is set to 0 1 Answer
Distribute terrain in zones 3 Answers
changing speed for 10 seconds and then return it back to its value 0 Answers