Yield can be used in any method, including anonymous ones (Edit: At least in Boo) . I use this technique very often for various enumerable generators. The problem is that yield and unity coroutines are not the same thing.
Yield turns any method you use the keyword in to a generator. Calling the “method” will actually consturct an enumerable object. Iterating over it will always cause the part of its code to be executed, and the yielded value be returned as Current. Example (i write in Boo, sorry ):
/// anonymous method with an array of int as input, enumerable of int as output
/// this generator will yield any value from the input array that is even.
getEvenInts = def( input as (int) ) as IEnumerable[of int]:
for val in range(input.Length): //for in boo is like foreach in c# i think
print("testing $val")
if val%2 == 0:
yield val
///
for num in getEvenInts((1,2,3,4,5,6,7,8,9,10)):
print("$num is even")
Iterating over getEvenInts will always execute bit of code until it hits yield. Then the control returns to the cycle (print the value), then again continue in generator code from the last yield.
The print out will be:
testing 1
testing 2
2 is even
testing 3
testing 4
4 is even
......
Notice the order of prints. It’s not all testing prints and then all “is even” prints, it jumps in and out.
Now you understand how generators and yield work, you can try to understand unity coroutines, it’s quite simple.
When you call StartCoroutine(), you give it the enumerator as argument. Unity will do the first iteration over it (executing part of the code) and read the yielded value. When unity receives one of the values like WaitForSeconds, it will save the enumerator in an internal queue, remembering when it should continue. Every next frame after, unity checks the queue for enumerators that should be continued. After the time passed and the check returns true, unity simply iterates over the enumerator once again, repeating the procedure until the enumerator ends (just like the foreach cycle ends when there are no more objects in the array).
Now to find out why your code doesn’t work.
First, i just realized that maybe the first compilation problem is that c# actually doesn’t support yield in anonymous methods Boo is OK with that. That problem you can fix by removing the anonymous methods and making it your class member methods (again i am no expert in c#, but i believe the => arrow pointing to a {} code block is responsible, try to point the arrow to a member method name?
This will fix the compilation error, though your coroutine will still not work. At least it does’nt say in the docs that the callback from Authenticate() “can be a coroutine” which would mean the unity will detect if the method is a generator and start the coroutine for you.
Unity won’t react to WaitForSeconds unless the generator is iterated over from the unity engine, being started by StartCoroutine call. To fix this, you need:
-
A member method to be used as coroutine. Just copy the code from the block after => lambda assignment and make it a separate (non anonymous) method.
void AuthenticationCallback(bool success)
{
if (success)
{
Debug.Log (“Successfully logged in”);
SuccessLogin.active = true;
yield return new WaitForSeconds (2);
SuccessLogin.active = false;
}
else
{
Debug.Log (“Log in failed”);
FailedLogin.active = true;
yield return new WaitForSeconds (2);
FailedLogin.active = false;
}
}
-
To start the coroutine. So where the original anonymous method was, replace it with
=> { StartCoroutine(AuthenticationCallback(success)) }
Now you\ve created an anonymous method that tells the monoBehaviour to start the coroutine, passing the argument to it as well. The generator method *the one using yield) is correctly iterated over by the unity engine and WaitForSeconds are received by the engine.
I hope i clarified the problem to you