Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
6
Question by jacksmash2012 · Jun 28, 2012 at 02:33 PM · yieldcoroutines

question about Coroutines and waiting for a function to finish

Let's say I have a function "f" that needs to wait until "g" is finished it's execution, but "g" has multiple yield returns in it. Something like:

 void f() {
   yield return StartCoroutine(g());
   // do something else now...
 }
 IEnumerator g() {
 
   // do something
 
   while (something)
     yield return null;
 
   // so something else
 
   yield return null;
 }

So in this case, I don't want f() to continue until the final "yield return null" has been called in g(). But my understanding is that f() will continue after the very first time "yield return null" has been called.

I suppose the while loop in g() could just be empty. That would be a fix. But is there ever a case where we need multiple "yield return null" statements in a function, but need to "wait" for the last one?

Thanks for any insights into this. I've read the following:

http://docs.unity3d.com/Documentation/ScriptReference/index.Coroutines_26_Yield.html

But I don't find it to be the most helpful piece of documentation. It uses the statement: "The yield statement is a special kind of return, that ensures that the function will continue from the line after the yield statement next time it is called." But that doesn't make sense to me, because the function WILL continue whether or not it is called again!

Thanks.

Comment
Add comment · Show 1
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image jacksmash2012 · Jun 28, 2012 at 02:40 PM 0
Share

Regarding my last paragraph, I now understand that the function continues after the end of the current frame. So this suggests that there may be situations where the above code would be needed. I want the while loop to pause until the end of each frame (until some global condition is met), but I still only want f() to continue after g() has finished completely.

1 Reply

· Add your reply
  • Sort: 
avatar image
25
Best Answer

Answer by Bunny83 · Jun 28, 2012 at 03:07 PM

If you yield return another coroutine like you did, it will wait until the coroutine is finished, but i guess you have trouble to understand what a coroutine is.

A coroutine is not a function that runs in some magic parallel thread. The yield statement is actually a C# feature. Functions that contain this statement have to return an IEnumerator. Such a function is called a generator-function. When you call the function it doesn't execute any of the code in it. It just returns an object that implements the IEnumerator interface. This object can be used to execute the actual code until the next yield statement.

In Unity you pass the result of the generator to StartCoroutine. This function will store the given object internally on the MonoBehaviour instance and will take care of executing it.

The coroutine scheduler in Unity will drive the execution when it's time to do so.

When you yield return in a coroutine, the coroutine is exited at this point and will return the given object to the scheduler. WaitForSeconds is just a class that holds a float value. The scheduler will check what the coroutine returns and "schedule" the coroutine for continue when it's time to do so. When you yield another coroutine (a Coroutine is returned by StartCoroutine), the scheduler will suspend the execution until the yielded coroutine has finished.

So in your case the coroutines should look like this:

 IEnumerator f() {
     Debug.Log("f() started");
     yield return StartCoroutine(g());
     Debug.Log("f() is done");
 }
 
 IEnumerator g() {
     Debug.Log("g() started");
     while (something)
         yield return null;
     Debug.Log("g() is done");
 }
 
 // Somewhere else you start f() like this:
 
 StartCoroutine(f());

this will print:

 "f() started"
 "g() started"
 "g() is done"
 "f() is done"

If you still have trouble to understand how they work, take a look at this custom CoroutineScheduler. The author also have this great blog which explains a bit what happens behind the scenes

Comment
Add comment · Show 4 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image jacksmash2012 · Jun 28, 2012 at 03:10 PM 0
Share

Shoot! I haven't finished digesting your response yet, but I realized that I had the wrong return-type for the g() function. I've edited that.

avatar image jacksmash2012 · Jun 28, 2012 at 03:17 PM 0
Share

Your explanation is excellent. Let's see if I understand correctly: for the above to work as you described, then the f() function must also be a coroutine so that it gets suspended until g() is finished. If I just have:

void f()... IEnumerator g()...

Then that won't work, because f() won't be suspended. Am I close?

avatar image dylanfries · Jun 28, 2012 at 03:44 PM 4
Share

Yes, if you change f() to be public void f()

it would start coroutine g(), then continue with f giving you

f() started g() started f() is done g() is done

making f() type IEnumerator and calling yield return g() basically is stopping f() at the yield until g() returns, then when g() completes and returns, f() will continue from that line (not beginning at the top). It's kind of like saying " wait here until this finishes, then continue" rather then, if you just start a new coroutine (g()) from a regular function its saying " go do this thing independently but continue running without waiting for a response". I know this is a rather untechnical description of it but it might help.

avatar image jacksmash2012 · Jun 28, 2012 at 04:21 PM 0
Share

Excellent. Thanks to both of you.

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

6 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Coroutines and states 1 Answer

Are coroutines freezing my game? 0 Answers

How do I properly use Coroutines, yield and animators to sequence commands ? 2 Answers

Inconsistent StopCoroutine behavior with CustomYieldInstruction 1 Answer

Problem with Stopping Nested Coroutines: Control Never Returned to Parent 3 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges