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 sebas77 · Mar 28, 2012 at 03:50 PM · yield

yield and coroutines, how do they actually work?

Hello,

I think I have a good understanding of the yield keyword, still I do not understand how practically something like :

 IEnumerator Example() {
        print(Time.time);
        yield return new WaitForSeconds(5);
        print(Time.time);    }

can work.

I am sure that the MonoBehaviour StartCoroutine registers the single routines, which are then called every frame. In this way the Iterator Block is recalled as it should be. It is everything clear, expect the fact I do not understand how the iterator block can know that the YieldInstruction is actually finished. I mean I was expecting something like yield break, but things like :

yield return www o yield return WaitForSecond() look like they should never end OR actually called just once.

Please help me to understand what is the trick Unity does.

N.B. I was expecting at least to see the WWW class or the YieldInstruction to be IEnumerable, but it is not even this the case :(

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 MaxKarpinsky · Feb 14, 2018 at 01:10 PM 0
Share

https://stackoverflow.com/a/32469037/6603717

2 Replies

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

Answer by Statement · Mar 28, 2012 at 04:17 PM

Unity just make use of enumerators. The compiler will add some extra code to the function so the code can jump to where it yielded next time it is enumerated. This allow us to execute parts of the code in small steps.

You can do your own code that goes through an enumerator in the same way.

 IEnumerator e = Example();
 
 while (e.MoveNext())
 {
     Debug.Log("Yielded: " + e.Current);
 }

When yielding a WaitForSeconds, Unity will wait with calling MoveNext until the duration has passed. If the object yielded is null, it will wait until next frame. If it is a WaitForSeconds, it will read the duration. "Simple" as that.

To get an idea about this, you could think:

 if (e.Current is WWW) ... // call e.MoveNext when the download finished! 


You can make your own system like this by keeping a list of pairs of IEnumerator and Func predicates (for letting know if it is ok to advance to the next yield).

Each update, you loop through all pairs, check if the predicate allow moving the enumerator. If it does, move the enumerator and set the predicate to the next criteria. For example, if e.Current was WWW, you might make a predicate to check if WWW has completed or not. If it is WaitForSeconds, you make a predicate that return true once the time reaches Now + Duration.

I hope you understand more about how this works. IEnumerator is nothing specific with Unity, so you can read more about IEnumerator online to go more in depth.

Comment
Add comment · Show 6 · 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 sebas77 · Mar 28, 2012 at 04:24 PM 0
Share

let's make a better example:

IEnumerator WaitForSecondsBlockIterator() { yield return WaitForSeconds(2); }

IEnumerator e = WaitForSecondsBlockIterator();

while (e.$$anonymous$$oveNext()) { Debug.Log("Yielded: " + e.Current); }

if I this is corret, I have new questions:

how many times this line is actually called:

yield return WaitForSeconds(2);

once or every frame until the 2 seconds are passed?

and I do not understand when exactly $$anonymous$$oveNext starts to return false and why

avatar image Statement · Mar 28, 2012 at 04:26 PM 1
Share

Once. It is yielded (returned, then continue execution there next enumeration), and the code will not be called until after 2 seconds. $$anonymous$$oveNext return false when you reach the end of the method or you yield break;

avatar image sebas77 · Mar 28, 2012 at 09:37 PM 0
Share

I wonder now how the system could work if an Enumerable yield another Enumerable function (which could be async in its turn)

avatar image Statement · Mar 29, 2012 at 01:32 PM 0
Share

Unity will not pick this up. You need to yield return StartCoroutine("OtherCoRoutine") for it to pause execution. If you want to support nested enumerators, then you have to write your own code around it. It shouldn't be too hard if you follow the advice I gave in my post. if (e.Current is IEnumerator) ...

avatar image Neeko · Jan 10, 2014 at 02:44 PM 0
Share

I usually hate to link dump, but this provides a much better, thorough explaination of how coroutines work http://www.altdevblogaday.com/2011/07/07/unity3d-coroutines-in-detail/

avatar image ohthepain Neeko · Apr 26, 2021 at 11:40 AM 0
Share

Updated link : link text

avatar image
5

Answer by Douvantzis · Jun 15, 2016 at 01:37 PM

As @Statement explained, Unity makes use of enumerators. However, I'd like to go a bit deeper on how I think it works internally.

When your co-routine returns an object by calling yield return new SomeType(), Unity will check its type. If it is of type YieldInstruction or Ienumerator, Unity will call MoveNext() on that enumerator as well. As long as MoveNext() returns true, Unity will continue iterating over this enumerator in the next frames and it will not continue your initial coroutine execution.

From within your returned IEnumerator you can yield return another IEnumerator. This way you can chain multiple Enumerators. Inception! I know!

If you wonder how WaitForSeconds and other extensions of YieldInstruction work internally, check out this documentation page. It seems that YieldInstrction could implement the Ienumerator interface like this:

 class YieldInstruction: IEnumerator {

         // default implementation that must be overridden
         public bool keepWaiting { get { return false; } }
 
         public object Current { get { return null; } }
 
         public bool MoveNext() { return keepWaiting(); }
 
         public void Reset() {}
 }

Comment
Add comment · Show 1 · 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 huulong · Apr 29, 2017 at 07:54 PM 1
Share

Just found the CustomYieldInstruction too, after discovering WaitWhile and WaitUntil at the same time via autocompletion. They seem convenient to wait for scene loading and so on.

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

10 People are following this question.

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

Related Questions

The name 'Joystick' does not denote a valid type ('not found') 2 Answers

Yield function goes slow sometimes/differently? 2 Answers

Script to set character to active after 3 seconds not working 1 Answer

making LateUpdate wait for Fade in/out guiText 1 Answer

WaitForSeconds/Yield problem 1 Answer


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