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
0
Question by tigertrussell · Mar 01, 2015 at 04:35 AM · coroutinecoroutines

Nested Coroutines: last coroutine quits early

Greetings,

I am trying to nest Coroutines. It seems to work OK, except that the last nested coroutine exits early.

In a nutshell, here's what I'm trying to do (in pseudocode)

 // start coroutine "add to scene"
 
    // start coroutine "fade to black", yield
 
    // does some simple logic
 
    // start coroutine "fade in from black", yield

As you can see, I want my "add to scene" Coroutine to be "wrapped" in the complete execution of two other Coroutines, fading a Unity.UI Panel in and out (using Color.Lerp and adjusting the alpha channel of the start color to determine the end color).

The first Coroutine "fade to black" works totally fine; it fades out as expected. Then, the simple logic is performed, as expected.

However, the final Coroutine "fade in from black" seems to yield only one time, even though I am using the same type of yield return statement on it.

What am I doing wrong here?

Here's some mildly redacted example code:

   private IEnumerator TransitionToScene(string sceneName) {
     Debug.Log("Transitioning. Starting fade out...");
 
     //Start a fade-out
     yield return StartCoroutine(Fade(FadeStyle.FadeOut));
 
     // OTHER STUFF IN HERE
 
     Debug.Log("Loaded! Fading in, now...");
 
     //Start a fade-in
     yield return StartCoroutine(Fade(FadeStyle.FadeIn));
 
     Debug.Log("Fade in complete");
   }

Here's the actual "Fade" Coroutine, also:

   //Create a Coroutine which will fade in or out
   private IEnumerator Fade( FadeStyle style, float fadeTime = .25f ) {
 
     //Early exit for invalid fade style
     if(style == FadeStyle.Invalid) { Debug.Log("INVALID FADE: Early-exit."); yield break; }
 
     Debug.Log("Fade coroutine started...");
 
     //Keep track of our fade progress out here for the coroutine...
     float fadeProgress = 0;
 
     //Grab the start color
     Color start = fadeImage.color;
     //Create a target color based on the start color...
     Color end = start;
     //If we're fading in, the target alpha is 0. If we're fading out, it's 1.
     end.a = style == FadeStyle.FadeIn ? 0 : 1;
 
     Debug.Log("Fading from " + start + " to " + end);
 
     //While we have not faded, yet...
     while(fadeProgress < fadeTime) {
 
       string inOrOut = style == FadeStyle.FadeIn ? "In" : "Out";
       Debug.Log("Fade " + inOrOut + ": " + fadeProgress  + " / " + fadeTime);
 
       //Calculate how far along we should be in the color transitions...
       float lerpVal = fadeProgress / fadeTime;
       Color newColor = Color.Lerp(start, end, lerpVal);
 
       //Apply it
       fadeImage.color = newColor;
 
       //Increment time
       fadeProgress += Time.deltaTime;
 
       //Continue next frame
       yield return null;
     }
 
     Debug.Log("Fade coroutine complete... (" + fadeProgress + " / " + fadeTime + ")");
   }


And, finally, some debug output:

 Fade coroutine started...
 UnityEngine.Debug:Log(Object)
 <Fade>c__Iterator0:MoveNext() (at Assets/SceneManager.cs:75)
 UnityEngine.MonoBehaviour:StartCoroutine(IEnumerator)
 <TransitionToScene>c__Iterator1:MoveNext() (at Assets/SceneManager.cs:160)
 
 
 Fading from RGBA(0.000, 0.000, 0.000, 0.998) to RGBA(0.000, 0.000, 0.000, 0.000)
 UnityEngine.Debug:Log(Object)
 <Fade>c__Iterator0:MoveNext() (at Assets/SceneManager.cs:87)
 UnityEngine.MonoBehaviour:StartCoroutine(IEnumerator)
 <TransitionToScene>c__Iterator1:MoveNext() (at Assets/SceneManager.cs:160)
 
 
 Fade In: 0 / 0.25
 UnityEngine.Debug:Log(Object)
 <Fade>c__Iterator0:MoveNext() (at Assets/SceneManager.cs:93)
 UnityEngine.MonoBehaviour:StartCoroutine(IEnumerator)
 <TransitionToScene>c__Iterator1:MoveNext() (at Assets/SceneManager.cs:160)
 
 
 Fade In: 0.001157403 / 0.25
 UnityEngine.Debug:Log(Object)
 <Fade>c__Iterator0:MoveNext() (at Assets/SceneManager.cs:93)
 
 
 Fade In: 0.008806617 / 0.25
 UnityEngine.Debug:Log(Object)
 <Fade>c__Iterator0:MoveNext() (at Assets/SceneManager.cs:93)
 
 
 Fade coroutine complete... (0.2785531 / 0.25)
 UnityEngine.Debug:Log(Object)
 <Fade>c__Iterator0:MoveNext() (at Assets/SceneManager.cs:109)
 
Comment
Add comment · Show 10
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 tigertrussell · Mar 01, 2015 at 05:41 AM 0
Share

FYI I have commented out the Destroy(...) call having read that destroying an object which started a Coroutine can cause it to exit early. No avail.

avatar image tigertrussell · Mar 01, 2015 at 05:25 PM 1
Share

Looks like there is a spike in Time.deltaTime which causes the coroutine to complete super early.

avatar image gfoot · Mar 01, 2015 at 06:15 PM 0
Share

I agree with tigertrussell - I'd suspect that if the thing you're fading out to cover up is the spawning of a load of gameobjects, some of the scripts in those gameobjects are waking up and causing a spike in the time deltas. $$anonymous$$aybe if you delayed a bit before fading in, it would let those gameobjects settle before the fade begins.

avatar image tigertrussell · Mar 01, 2015 at 06:50 PM 0
Share

@gfoot hehe I'm OP ;) but you're absolutely right! that was the cause. I have temporarily solved the issue by doing a yield return new WaitForSeconds(1); but was wondering if there is any way to force it to go to the next frame? It seems like new WaitForEndOfFrame() waits until the end of the current frame; is there a way to wait until the beginning of the next frame?

avatar image gfoot · Mar 01, 2015 at 06:53 PM 0
Share

Haha ok :)

Simply yielding null or 0 or anything that Unity doesn't recognize will resume you on the next frame during the Update phase.

Show more comments

1 Reply

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

Answer by tigertrussell · Mar 01, 2015 at 09:51 PM

The culprit is how "progress" is measured within the Coroutine itself.

Take this code:

        //Increment time
        fadeProgress += Time.deltaTime;


Because Time.deltaTime can be very large, it is possible for the while-loop to quit execution very early. This can be handled with special cases or you can hack it and use something like yield return new WaitForSeconds();

Another thing I've thought about doing (but is not especially safe) is to do:

 if(Time.deltaTime < skipThreshold)

around the processing of the Coroutine to avoid incrementing the timer more than we want to.

Comment
Add comment · 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

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

22 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

Related Questions

NullReferenceException in StartCoroutine 1 Answer

How to stop a coroutine started in Script A from within Script B 1 Answer

Collection Change During Iteration 0 Answers

Why doesnt my coroutine ever end? 2 Answers

Is there a way to find out when a coroutine is done executing? 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