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 :_(

2 Answers

2

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 Mortoc'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 programming command. I think a coroutine would work, but your particular problem might not be the best way to learn them.

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;
}

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.