Recurring events are something I’ve been scripting for a while, but I’m never really sure of the best way to script it. And by recurring events I mean anything that will happen periodically without user intervention - so things like eyes blinking, NPCs wandering, lights flickering, etc.
I’ve seen this implemented at least 4 different ways (shown below). I typically do #1. I like the compactness of #4, but don’t like passing the function name as a string and not being able to pass parameters. I’m also uneasy about Invoke because it’s not well-documented (is it a Coroutine? Can I stop it once I start it? Can I use InvokeRepeating multiple times? etc.) and does a little too much “behind-the-scenes” for my peace of mind.
Anyway, I was wondering if anybody else has any strong opinions on the best way to handle these kinds of events.
I think all of them are fine, though I don’t like #2 as much as the others since I personally don’t like those self-invoking functions.
For the most part I think it is again up to the real thing you want to achieve. For example, #3 is in my eyes the best way to implement something like a weapon were you only have a certain firing frequency.
#4 is nice if you want to start a certain recurring event in an Update()-like fashion some time during the game without the “real” Update() function being called until then.
#1 is good in case you want to fire events in a certain interval and not like in Update() every frame.
So everyone has it’s pros and cons, yet as mentioned I use #2 the least as I don’t see any advantage for that, especially compared to #1, which is more controllable in my eyes.
But bottom line is: None of these is actually “wrong”. It depends on the situation and one might fit better than others.
I find I use option #3 during development so I can easily access the timing variable from the inspector. If the routine can’t be evaluated into a run / no run and it takes up a lot of time then I start thinking about not running it in the update and using InvokeRepeating. Perhaps it’s my code style but I seem to run into little gotchas and end up writing extra guard / sanity check code in my invoked statements which can possibly distract me from my main goal if I let it.
One thing that did occur to me after posting this… if the recurring event needs to run script in more than a single frame then #1 and #2 quickly become the best choices. Eyes blinking and flickering lights would be good examples of this. Blinking eyes logic would be something like, wait 5 seconds, close eyes, wait 0.5 seconds, open eyes, repeat. That’s the kind of thing best suited to a coroutine with yield statements.
Probably use something like #3 - invoke repeating is fine if you have something that is repeating at a set interval, but in my games thats usually just a timer, most other things have slight off sets or randomness to bring them to life.
Something like this:
var frameRate : float; //this could be inherited from a master setting
private var frameFire : float;
var metronome : boolean;
function Update() {
if ( Time.time >= frameFire ) {
frameFire = Time.time + frameRate;
//see the rate in you console for fun:
if (metronome) {
Debug.Log("tick");
metronome = false;
} else {
Debug.Log("tock");
metronome = true;
}
}
}