Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 12 Next capture
2021 2022 2023
1 capture
12 Jun 22 - 12 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
1
Question by UnityBrains · Sep 29, 2019 at 09:21 PM · coroutineyieldpositioningwhilestartcoroutine

Yield position within while loop in coroutine

I have this code:

 public bool A = true;
 public bool B = true;
 
 public void Initialise()
 {
     StartCoroutine(Appear());
 }
 
 public IEnumerator Appear()
 {
     yield return StartCoroutine(TestA());
     Debug.Log("Should only be one of these");
     yield return StartCoroutine(TestB());
 }
 
 public IEnumerator TestA()
 {
     while(A)
     {
         Debug.Log("A");
         yield return null;
     }
 }
 
 public IEnumerator TestB()
 {
     while(B)
     {
         Debug.Log("B");
         yield return null;
     }
 }


Can someone explain why the output looks like this? Why are there two instances of a single "A" and "B"? (I manually uncheck "A" and "B" in sequence in the inspector panel while the game is running to execute this test if you were wondering)

alt text

Also, if I move the yield return null; to be above the debug output

  public IEnumerator TestA()
  {
      while(A)
      {
          yield return null;
          Debug.Log("A");
      }
  }

the resulting debug output is as expected: alt text

I am at a loss as to how the thread executes and why the initial debug output is considered separate from the others. Any help would be appreciated.

capture.png (21.4 kB)
capture2.png (15.4 kB)
Comment
Add comment
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

1 Reply

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

Answer by Bunny83 · Sep 29, 2019 at 10:01 PM

That's pretty easy to explain. When you start a coroutine you actually create an IEnumerator instance and hand it over to unity by passing it to StartCoroutine. StartCoroutine will immediately run your coroutine one step up to the first yield statement. At this point the coroutine will be queued into the normal coroutine scheduler and depending on the value yielded it will decide when to re-schedule it. After this the StartCoroutine call will actually return.


So the code that comes after your StartCoroutine call will resume once the started coroutine reaches it's first yield statement. The reason why the debug log shows up as a seperate entry is the different stacktrace. The first call comes from your direct call of StartCoroutine. All subsequent calls of your Debug.Log calls come from the internal coroutine scheduler so it has a different stacktrace. Just have a closer look at the two logs (the lower section of the log window when you select one of the messages.)


edit

Please note that coroutines are not threads. They implement cooperative multitasking. All coroutines run on the main thread. Unity just utilizes the concept of C# iterator blocks. The C# compiler will turn a method that contains yield statements into a generator method which when called doesn't execute a single line of your code but instead it creates an instance of a compiler generated hidden class. This class instance is actually a statemachine object that represents your coroutine code. This object has a MoveNext method which when called will execute all code between the last yield and the next one and then return. So all Unity actually does is when you start a coroutine, Unity will call MoveNext once from inside StartCoroutine which will move the statemachine to the first yield statement. The iterator object will be stored internally by the coroutine scheduler.


As you can see in the flow chart all pending coroutines which have yield one of the common values (null, WaitForSeconds, WWW or chained coroutine calls) will actually be resumed just after your Update callback when they are due.


If you want to know more about iterator blocks and how they work, I recommend this blog post. If you want to get a better understanding how the coroutine scheduler works, have a look at this custom coroutine scheduler implementation on the Unity wiki.

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 UnityBrains · Sep 30, 2019 at 12:56 AM 0
Share

Perfect - thanks for your answer.

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

121 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 avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

How To Create Coroutine Delegates? 1 Answer

C#: Use of while loops inside of a coroutine 2 Answers

StartCoroutine important for using yield? 1 Answer

JS Wait for a function to complete - no WaitForSeconds 1 Answer

Coroutines and states 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