- Home /
How can i manage an instant event with float type
Hi, guys. I have a tricky problem when i try to manage an event ocurring when a variable float reaches a certain value. I use:
varfloat+=Time.deltaTime;
if (varfloat>= instant) RunEvent();
This works fine, but what happens when i only want this event to trigger once? First i thought to calculate every tick from Time.deltaTime but it happens Time.deltaTime is not constant so this won't work:
if (varfloat >= instant && varfloat < instant+Time.deltaTime) RunEvent();
Because i dont know how long the next frame will be (it's not constant). I also tried Mathf.Approximately but the approximation is smaller than frame times so it does not work either. It is important the event to be called ONCE.
I hope you understand my problem and you had to deal with this before :_(
Answer by Owen-Reynolds · Dec 01, 2013 at 06:57 PM
General timer comment: Unity already runs a clock for you, so it's easier not to add time.deltaTime
yourself. Imagine you want to wait 5 minutes for real. It's 2:43 now, so you write down 2:48. Then you just keep glancing at the clock until 2:48.
Non-coroutine solutions might be 1) when you fire the event, reset the time to make sure it can't go off again:
// setting a 2 second delay:
timerVar = Time.time + 2.0f;
// waiting 2 seconds:
if(timerVar > Time.time) {
RunEvent();
timerVar=9999999;
}
Or, 2) use an extra "I'm waiting to fire" variable.
bool waitingForEvent1=false;
// setting a 2-second delay:
timerVar = Time.time + 2.0f;
waitingForEvent1=true;
// waiting 2 seconds:
if(waitingForEvent1 && timerVar>Time.time) {
RunEvent();
waitingForEvent1=false;
}
Your comments are nice, Owen, but i wrote down the time example to simplify the problem. Actually varfloat is the position of a car on a path, and it is calculated from speed and player decissions so i will never know the delay before the car is at the desired point (instant). Anyway, the solutions you propose in your answer are fully functional but i cant use option 1) because i need the timer (the position of the car) keep growing along the path (or car will stop), and option 2) is nice but i will need lots of "flag variables" because there are a lot of points in the track (positions on the path) that trigger events.
An old trick to never repeat something during "advancement" is to have an int variable like "lastPlaceTrigered." If you're past waypoint6, do the 1-time thing if lastPlaceTriggered is less than 6. Then change LPT to 6.
That's a really elegant solution to avoid declaring many "flag variables". But after reading your comment about coroutines they seem very interesting, i hadn't use them before, so i will take a look at their behaviour even if finally i use the int variable solution. Thank you very much, Owen. Turn your comment into an answer so i can accept it.
Answer by Mortoc · Dec 01, 2013 at 06:37 PM
Sounds like a decent time to use a Coroutine. Something like this:
IEnumerator RunEvent()
{
while(varfloat < instant)
{
varfloat += Time.deltaTime;
yield return 0;
}
RunEvent();
}
Could replace the while loop with 1 line like:
yield return new WaitForSeconds(timeDelay);
There's also a short-cut coroutine if you only want to add a delay on a 0-input function: Invoke("RunEvent", delay);
...and, rename to not have 2 RunEvents.
Well i think $$anonymous$$ortoc's method won't work for me because i need varfloat out of the coroutine for further calculations. Still i dont understand how that function works. When varfloat < instant it increases varfloat and returns waiting for another call. When varfloat is equal or greater than instant then it calls itself again and enters in a void loop.
Coroutines are special things. The yield return 0;
means: pause right here until next frame. It's like a sleep()
command, and unlike any normal program$$anonymous$$g command. I think a coroutine would work, but your particular problem might not be the best way to learn them.
Your answer
