|
I have one routine, Ideally, I'd just yield the IEnumerator returned by
However, Unity doesn't seem to recursively iterate over IEnumerators, so Func2 yields just once. An alternative is to manually iterate over the IEnumerator,
but I was looking for a less clunky solution, much like the way I can yield a WWW object and wait for its completion? EDIT: Removed superfluous yield statement in func2. It turns out, that MoveNext should be called before accessing IEnumerator.Current
(comments are locked)
|
|
You want:
For example: You want to create an object that does three in this order: fade in, move, and then shoot a gun. But since moving and shooting is very common in this game, you want to have a single function that simple does them both. You could write something like:
This will essentially output:
The numbers are in seconds, and you can see that the original FadeAndMove courtine takes 5 seconds to complete. The desired behavior. This is correct answer. yield return StartCoroutine( Func1() );
Apr 28 '10 at 02:07 AM
evelynliu
Sweet! Thank you very much :)
Apr 28 '10 at 05:11 AM
KvanteTore
That's beautiful. What a great feature of the unity framework!
Feb 16 '11 at 09:45 AM
Ouchie
I have since learned about some snags in this approach. If one of the coroutines happens to throw an exception, the execution of all the nested coroutines would stop abruptly. I've therefore fallen back on the approach of manually iterating through the nested IEnumerators.
Oct 05 '11 at 12:33 PM
KvanteTore
This doesn't work on
Jan 04 at 01:51 PM
Cawas
(comments are locked)
|
|
You can do this by "manually" iterating through the 2nd coroutine's IEnumerator object that it returns, like this:
Output: yes, that is the same solution as I posted in my second code snippet, but it's a bit clunky. I was hoping I had overlooked something more elegant :)
Mar 30 '10 at 09:38 AM
KvanteTore
Only, you yield null from the Func2 instead of passing on the yielded value from Func1. Is there a reason for that?
Mar 30 '10 at 09:39 AM
KvanteTore
Oh, sorry I completely overlooked your second snippet! Um, no reason really - The code in Func1 is executed by calling MoveNext() so I'm not what difference (if any) it makes to yield null rather than the return value of Func1. I have a feeling that it only affects how long Unity waits before calling the coroutine again.
Mar 30 '10 at 09:45 AM
duck ♦♦
Actually, you should use
Jan 06 '12 at 09:33 PM
Calvin1602
@Calvin1602: absolutely ;) I've just read the question and the answers. After reading this one i just wanted to add a comment like yours, but i've found your comment before i start writing ;)
Jan 07 '12 at 12:42 AM
Bunny83
(comments are locked)
|
|
You may be over-thinking this...
You want this statement to "hold" until So if you want to call
And then start a new coroutine with Ah. That would work if
Mar 30 '10 at 08:30 AM
KvanteTore
And I don't want to block the entire Unity thread, I just want to halt the execution of Func2, coroutine-style.
Mar 30 '10 at 08:31 AM
KvanteTore
Inside of a coroutine, as far as I understand it, you wouldn't block the entire Unity thread, just that one coroutine. You could also just use standard C# threading instead of mucking around in coroutines. Start a new thread that loads your external resource, and then call an event when it's completed. It's essentially an asynchronous action, and there is tons of example code and documentation online regarding threads and events with respect to C#. If you want me to, though, I can write a small set of example code for you. Just let me know.
Mar 30 '10 at 04:30 PM
qJake
It appears most Unity specific methods are not thread-safe though. You can't, for instance, create an object that derives from a MonoBehaviour within a new and separate thread. If you call an event asynchronously (with BeginInvoke) it happens in a new thread and cant access Unity's API. I am using a separate thread to do background loading for some non-MonoBehaviour objects and then polling for completion from a Unity Coroutine. Seems to be working so far. The downside is you cant actually create GameObjects in the background apparently.
Nov 30 '10 at 09:47 PM
Antitheory
(comments are locked)
|
|
A way that is a bit cleaner is:
(comments are locked)
|
|
You can also pass the IEnumerator from another function This could allow all sorts of extensions, like a workaround for default parameters or classes or functions which cannot for whatever reason be called with a coroutine.
(comments are locked)
|

I made a suggestion to help implement nested coroutines in Unity: http://feedback.unity3d.com/forums/15792-unity/suggestions/636531-make-yieldinstruction-extendable
I believe there's no need for the whole line
yield return e.Current;or at least on my experiments I removed it and nothing wrong happened. Since this is actually a better solution than usingStartCoroutine, because of static methods for one, I think it's quite relevant to make it shorter. ;-)you'll need the yield return e.Current line in order to actually give control back to the unity engine. without it the innermost coroutine will be run as if there were no yield statements at all.
@Cawas, it turns out that IEnumerator.MoveNext should be called before IEnumerator.Current is accessed. I've updated the question to reflect this.
Now, reading it as it is, without knowing the line was removed, that "edit" comment makes little sense... And your link is to
IEnumerable, which is another thing and doesn't say anything aboutMoveNextbeing first, unlike the proper link: http://msdn.microsoft.com/en-us/library/system.collections.ienumerator.aspx so, nice finding you did there! :-)