what is the use of IEnumerator function
IEnumerator
there isn't a function, it's a return type. C# doesn't have functions either (but I know what you mean) - in C# we call them methods.
IEnumerator being so called implies it is an interface, so any class that implements the IEnumerator interface can be returned by this method
In practice in this use it seems that it's actually more of a hack than intending to provide the true intent of an enumerator, which is to step-by-step rifle through(or generate) a collection of things.
When you use a yield return
statement within a method "some magic happens" whereby it's not a return
in the classic sense, but creates a facility whereby the code can resume from where it left off (calling for the next item out of the returned enumerator will cause the code to resume from after the yield, with all the state it had before, rather than starting over).
If you look at the MSDN example for yield:
public class PowersOf2
{
static void Main()
{
// Display powers of 2 up to the exponent of 8:
foreach (int i in Power(2, 8))
{
Console.Write("{0} ", i);
}
}
public static System.Collections.Generic.IEnumerable<int> Power(int number, int exponent)
{
int result = 1;
for (int i = 0; i < exponent; i++)
{
result = result * number;
yield return result;
}
}
// Output: 2 4 8 16 32 64 128 256
}
The loop is controlled by i
; if this wasn't a yield return
then this wouldn't function as intended (it couldn't return an enumerator for a start but we'll leave that out). Suppose it was just a normal return
, the loop would never loop at all; the code would enter, start the loop, hit the return
, and just return a number one time and all memory of where the loop was would be forgotten.
By making it a yield return
, an enumerator is returned instead, and a small set of "saved state" is set up whereby the loop can remember the current value of i
- each time you ask for the next value, the code resumes where it left off from (ie just after the yield), the loop goes round again and a different value is yielded. This continues up to the max of course.. at which point the returned enumerator says it has no more items
You could yield forever, too.. If the code can never escape the loop then it will yield/generate forever
In this case you have to use yield return new WaitForSeconds
because that's how WaitForSeconds is intended to work. Yielding gives up an enumerator to the calling method, which is then free to enumerate it. From the docs it looks like this is deliberately done on the next frame, so using yield (perhaps repeatedly) is a way of arranging a block of code that occurs across several frames without having some sort of external state management that remembers where the process is up to and a wordy
- if state = 1 then close the door and add 1 to the state,
- else if state = 2 then light the torch and add 1
- else if state = 3 ...".
You can just
- yield,
- close the door,
- yield,
- light the torch,
- yield ..
Can't we do this by this process
Sure, looks reasonable; look at the clock 100 times a second and if 0.5 seconds have passed since you first looked at the clock, spawn the obstacles
I'd imagine (never used Unity; don't profess to know anything about it other than having read the docs for this one function) that your Update loop has a lot more to be getting on with, so handing a process off to a dedicated wait-then-do is more efficient than spending all your time looking at a clock and carrying out a potentially complicated calc to work out if you should do something; most things in life that start out as poll-every-x-milliseconds benefit from being switched to an "if the event occurs, react to it" way of working