- Home /
Decreasing values over seconds
How to make specific variable decrease by 1 in exactly 1 second? I mean exactly 1 per exatly 1 second, so using Time.DeltaTime is not accurate method. Is yield WaitForSeconds method more accurate than this?
Becaue if you multiply your value by Time.DeltaTime it will not give you integer value, when you add them you will not receive 1, but something around 1.
Well, you could use the System.DateTime class but except if you are doing something for a swiss clock company, I would guess deltaTime is good enough.
What about "yield WaitForSeconds()" method? Or "InvokeRepeating" method?
Answer by 237641 · Nov 04, 2014 at 07:46 PM
I don't really understand why time.deltaTime wouldn't be accurate enough but maybe your using it wrong. Try this. I've attached the output so you can decide for yourself if its accurate enough for you.
public float timeLeft = 1.0f;
timeLeft -= Time.deltaTime;
if (timeLeft <= 0)
{
//do something
timeLeft = 1.0f;
}
This will never work for being "in exactly 1 second". While the total time should match this will give various float results for timeLeft as Time.deltaTime is how long it has been since the last frame. This varies according to frame rate and will only equal an exact int value at random times throughout its use. You could then use rounding but it is making everything far harder than it really needs to be...
Answer by JazzWolf · Nov 04, 2014 at 07:32 PM
Coroutines might be your answer. Instead of updating every frame, they can be calculated over a couple frames and even given time delays before running again. I just learned about them myself and am not great with their implementation yet, but I think logically they will help you with your issue. Try digging through this and see if you can get anything from it: http://docs.unity3d.com/Manual/Coroutines.html
hope that helps. If I get time later today I may look into how that code would look. edit: Okay, I just fixed a ton of errors. This seems to work, but is probably over complicated and whether it is more accurate is still up for question. Also this is in C#.
//the variable you are decreasing
public float myVariable = 10f;
//I didn't know how to trigger the coRoutine only once, so I used a switch
public bool begin = true;
void Update () {
//coroutines aren't exclusive, so this makes sure it is only run one time
if (begin == true) {
//calls the coroutine
StartCoroutine ("Decrease");
begin = false;
}
}
//coroutine decleration
IEnumerator Decrease (){
while (myVariable > 0)
{
myVariable -= 1;
yield return new WaitForSeconds(1);
}
}
}
so I'm sure this is overly complicated but I got it to work, maybe it helps. But there are definitely simpler ways to do it. Honestly just learned about coroutines and wanted to implement something with the,
This will never trigger, you are checking if myVariable is less than or equal to 0. It starts at 10 so will never decrease as it will always be greater than 0.
Change :
if(myVariable<=0)
for :
if (myVariable > 0)
I would still use the Invoke method for this rather than coroutines though.
(Edit : The more I read your code the more errors I see, you start this coroutine every Update(maybe 60 times a second), you have no checks to see if it is running already So this would, if you had written the code change I've written above correctly, reduce the value of "myVariable" to 0 in a fraction of a second...)
yeah I realized all of that. I'm going to edit it right now.
$$anonymous$$uch better :)
Apart from your code formatting....
The boolean switch is the right way to go for a coroutine, this is why I prefer Invokes for this type of thing.
Yeah.. my formatting is terrible. I am very new to all of this! And really? It's logical, but I felt silly doing it like that. $$anonymous$$aybe it is the best way though.. This may be a stupid question, but what about triggering it from Start() or an OnEnable? I haven't got to Invokes in my learnings yet, but reading your script makes sense to me. I'll have to start playing with those as well.
In case you are reading through these comments, $$anonymous$$rSoad's answer with InvokeRepeating is simpler and also probably more accurate.
Answer by MrSoad · Nov 04, 2014 at 07:42 PM
For a countdown timer(in js) do this :
//Change to whatever start value you want.
private var iTime_Left : int = 45;
//Start Countdown here, place this in your
//script where you need it.
//The first digit says when first to trigger,
//you don't want to take a second immediatley
//so 1.
//The second digit says haw often to run
//this function
if (!IsInvoking("subTake_Second")) {
InvokeRepeating("subTake_Second", 1, 1);
}
//Your countdown function.
function subTake_Second() {
if (iTime_Left > 0) {
iTime_Left = iTime_Left - 1;
}
}
Your answer
Follow this Question
Related Questions
make an event occur after so many seconds? 1 Answer
Load Level after "x" seconds 1 Answer
Creating function that lasts for x seconds 3 Answers
CountDown Timer Help (Seconds problem) 2 Answers
Shooting every second issue 1 Answer