Search Unity

Among all the shiny new features, there is a tiny one line in the Unity 5.3 release notes for a feature that I found useful and I think you will too. Custom coroutines, namely the new CustomYieldInstruction class, mean that you can now add your own coroutine yield operations in a very simple way. So let’s take a look at a real world example.

A real world example – A bugfix

I was recently investigating a bug in the UI Dropdown component, a Unity 5.2 feature. When Time.timescale was set to 0, the Dropdown component would only work once, then it would not reappear until timescale was set back to a non-zero value.

After a bit of debugging, we found out that the problem is in the Show function.


m_Dropdown is not null and is preventing the Dropdown from being shown.

Once shown, the m_Dropdown component is minimised and then destroyed. Well, it should be destroyed, but when the timescale is 0, this is not happening.

Take a look at the destroy function and see if you can spot the problem.


The title of this article may have given it away, but WaitForSeconds is the answer. WaitForSeconds uses scaled time. This means that if you tell WaitForSeconds to wait for 1 second and the timescale is 0.5, then you actually wait for 2 seconds (1 / 0.5 = 2). So using WaitForSeconds with a timescale of 0 means that you wait indefinitely (until the timescale is not 0). The Dropdown was never being destroyed after its first use, because we would get held up by the WaitForSeconds yield instruction.

The solution

We need to wait using unscaled time; the most elegant approach here is to add a new yield operation, a WaitForSecondsRealtime class. Clearly, if our own developers do not realise WaitForSeconds uses scaled time, then we need to address this. WaitForSecondsRealtime  should help reinforce this message. We also need to update the docs for WaitForSeconds (we never mention scaled time!).

This is how I discovered the CustomYieldInstruction, recently added for creating new yield operations.

Adding a new yield operation is very simple, here is the solution to our problem.


Any custom yield operation needs to override the keepWaiting property and once we want the yield operation to continue, we just pass back false.

Here is how our fix now looks:


In our example, we grab the real time and just test against it each check. It doesn’t get much simpler than that – oh wait, it does, because we now also have the WaitUntil and WaitWhile yield instructions. With these, we can provide a delegate to be called for our yield instruction test.

Here is an alternative way to solve our problem, assuming we wanted a 5 second delay.


So, a simple feature, but with a lot of potential. I guess the lesson learned here is: Remember to read the release notes, you never know what useful features you might find! If you like the custom coroutines, you should take a look at UnityEvents, another favourite feature of mine that you may have missed.


Subscribe to comments

Comments are closed.

  1. Is it just me or are code snippets as images really un-useful?

    1. Yeah I didn’t realise we had support for code snippets in our blogs. I now know better :)

  2. Thanks for the post, Karl!

    But from what you wrote, I was really worried that CustomYieldInstruction was too limited an API, especially for basic cases where you want to reuse a yield instruction instance to prevent too much GC pressure from high-frequency or persistent waits.

    I’m SUPER happy to know, from reading the new documentation, that you can also implement custom yield instructions by just implementing IEnumerator in any arbitrary class.

    But then I wondered, was this always the case even before 5.3?
    If so, I feel so stupid for not doing it that way before. At the same time though, nobody else seemed to catch on and post about it online in Unity tips blogs so was there something else to that?

    1. The ability to do this has existed for some time now but not many users were aware so its a way of making it more obvious. I also believe we have made some improvements to how Unity handles IEnumerator when yielding.

  3. Is this only “sugar” ? since it seems that it’s perfectly possible to achieve the same using your own IEnumerator returning method (which will block until certain conditions are met).

    With regards to the metnioned UnityEvents – i believe there are some horrendous things going on under-the-hood… something with the ArgumentCache class and its implementation of ISerializationCallbackReceiver. It allocates ridiculous amounts of memory… I think i reported this or only asked about it on the forums. I wonder if there’s something being done about it.

    1. I dont know anything about memory issues with UnityEvents. Use the bug reporter so its made official, you can then keep track of the progress.

      1. Actually i did report that: (Case 738249) ArgumentCache.TidyAssemblyTypeName allocates lots of memory

        1. Thanks. QA have not verified it yet. I’ll try and take a look at it next week.

  4. Unless I’m missing something, it seems strange for keepWaiting to be implemented as a property instead of a method.

    1. whydoidoit November 28, 2012 – 10:15 pm That happens when yiendilg in a coroutine the compiler has generated code that MonoDevelop cannot break on it does cause the debugger to appear to step to exit code don’t worry about it, it’s just the magic class doing its return.

  5. It’s great to see CustomYieldInstruction and WaitForSecondsRealtime finally make it into Unity! They will make a big difference.

    Hopefully another lesson learned here is the importance of eating your down dog food! The need for CustomYieldInstructions and an unscaled version of WaitForSeconds come up often when using coroutines in a project. Both of which have been requested many times over the past many years. Now if we can just get you to go ahead and add pause, exception handling, return values, and a few other tweaks to coroutines, that’d be great.

    1. I’m really sorry to ask for coriifacatiln on this I wrote an algorithm that creates an rtf javascript editor in a web page. The editor works flawlessly when the javascript file unminified is < 1000 lines. The work around I found for parsing large scripts was to setinterval and time my execution. If it took too long I'd set an interval to release the thread and reenter such that the browser wouldn't display the unresponsive script error.Are you saying this threading code will unlock the HTML ui layer and allow background processing to occur? If what you say is true, and the previous comment about ie supporting a variant of this is true, you could have just rocked my world let me know.M

    2. That’s a sensible answer to a chnalengilg question

  6. Umm, is it a typo or is m_items.Clear() really in the for-loop?

    1. You are the third person to mention this ;)
      It is now fixed but the loop calls an empty virtual function which I guess no one uses as its never been reported as a bug.

  7. Marc-André Jutras

    December 2, 2015 at 8:22 pm

    Why, oh why is that property a camel case?

  8. The problem with nearly everybody having missed Unity Events is that they were never advertised individually and independently from the new Unity 4.6 UI. People only know them from injecting click handlers into buttons and don’t even suspect that you can enable the whole new “mouse only” level of behavioural level design for non-techs. You can barely find some geeky pioneers on the YouTube sharing their “revelations” that, hey, it appears you can actually use Unity Events without the UI.

    1. Well we do have some learn material and the documentation also shows how to use UnityEvents but I guess It gives me something to write another blog post about ;)

        1. Also, it’d be really nice if we could edit posts we make here, in case we mess up the formatting :D

      1. With the bases loaded you struck us out with that anwsre!

    2. mick November 28, 2012 – 9:57 pm Question about stepping torhugh DoHijack() with the monodevelop debugger:50IEnumerator DoHijack()51{52while(true)53{54//Check if we have a current coroutine and MoveNext on it if we do55if(_current != null && _current.MoveNext())56{57//Return whatever the coroutine yielded, so we will yield the58//same thing59yield return _current.Current;60}61else62//Otherwise wait for the next frame63yield return null;64}65}When I break on line 59 and then step over (f10), the current instruction caret moves to line 63 even though it doesn’t appear to be executing that line (ie if I set a breakpoint on line 63 it wont’ get hit). What is going on here?

  9. Thank you for this important information.

    For a while now, the Timer class in my Waitress library has been supporting unscaled time. It can also be used in non-coroutine methods. You don’t have to implement and start a coroutine to be able to wait for something.

    Please see the code examples in documentation if you are interested in more info :

    Waitress on Asset Store :!/content/45719

  10. Is it really necessary in 2015 to embed code as an image on a website? Especially on a HiDPI screen these code blocks look like a blurry mess in comparison to the sharp text surrounding it…

    Also, where is the documentation of CustomYieldInstruction? I couldn’t find it in the API reference.

    1. I wasn’t aware we had support for code in blog posts, apparently we do so I’ll make sure to use text in the future. Its not in the docs yet as its part of the 5.3 documentation which is not on-line yet.

      1. Thanks for the reply, I just loaded the 5.3 beta to look at the implementation :)

        One suggestion, it would be nice to have something like this in CustomYieldInstruction:
        public virtual void DidBeginYielding(MonoBehavior parentMonoBehaviour) {}

        That way, one could start and yield on other coroutines and wait for them using parentMonoBehaviour. That could be useful if I want to use stuff like yield return new WWW(url); inside my custom yield instruction.

        1. Interesting. I am not too familiar with the coroutine internals but it would be nice to support some events such as that(Stop/Pause/Cancel etc)
          Best thing to do is add them as feature requests as its not something I can do at the moment and I don’t want any ideas to get lost.

        2. This will be possible, since now Unity properly handles IEnumerator when yielding. Actually CustomYieldInstruction class is just a small handy wrapper based on it:

          abstract CustomYieldInstruction: IEnumerator {
          public abstract bool keepWaiting { get; }

          public object Current { get { return null; } }
          public bool MoveNext() { return keepWaiting; }
          public void Reset() {}

          If you were to return another IEnumerator through Current, then coroutine would be suspended on that.

        3. @KARL In fact, that feature request exists since quite some time ago ;)

  11. I’m trying to work on nested coroutine these days by passing a stack to trace these nested coroutines and their real executing monobehavior. It’s working if I stop all the coroutines by clear the stack, however if I want to stop the top of the stack, the parent coroutine won’t proceed for the terminated coroutine just stopped without any break yield instructions. With this feature I think I can make something useful. However, it would be better if nested coroutine could be supported by Unity natively.

    1. This will be possible, since now Unity properly handles IEnumerator when yielding. Actually CustomYieldInstruction class is just a small handy wrapper based on it:

      abstract CustomYieldInstruction: IEnumerator {
      public abstract bool keepWaiting { get; }

      public object Current { get { return null; } }
      public bool MoveNext() { return keepWaiting; }
      public void Reset() {}

      If you were to return another IEnumerator through Current, then coroutine would be suspended on that.

  12. Not sure but, isn’t the line “m_Items.Clear();” also a bug? For it is inside the “for” instruction so it will clear all the list in the first for step.

    1. Yes Shawn Halwes beat you to that one ;)

      1. They just _REALLY_ wanted to clear that list out.

  13. It is good news.
    but i really miss some features, especially when I do work on state machine code.
    I don’t think it big issue to implement for you it is so easy
    PauseCoroutine, ResumeCoroutine, Get progress of Coroutine, WaitCoroutine ( make Coroutine pause till another done) , GetCoroutine , … , … and so on
    May be also if you add editor window to show all current running Coroutines.

    This will make Coroutines amazing full solution for state machine.

    1. Post your feature requests here

      1. A feature like that has been requested at least more then once and more then a year ago, why not just make it happen? :(

        1. I’m not saying it isn’t happening, just wanted to make sure its captured as a feature request.
          I actually think its a good idea.

    2. Your thkining matches mine – great minds think alike!

    3. Yup. My only point here really is that they are motsly equivalent.Holy cow though I find CPS code to be impossible to read and impossible to debug.We’re getting more and more of it in the world and good god is it ugly.Callbacks are a nasty nasty way to write code.

  14. Does returning ‘false’ from ‘keepWaiting’ guarantee that this object is never used again inside Unity internals, so we can organize a pooling mechanism for these custom yieldables to reduce GC pressure?

    1. Interesting question. I see no reason why you could not pool them, once false is returned we don’t use it any more so a pooling system seems quite possible and not all that hard to do.

      1. It would be a very nice feature, if CustomYieldInstruction received some kind of notification when it’s stopped by StopCoroutine or by destroying host object or any other way removed from the pending list.

        1. I agree that would be useful. I don’t think its possible at the moment. Its not something I can just add at the moment so please add it as a feature request ;)

  15. Great stuff. Cant wait to update my task library. Should be able to reduce a bit of bloat.

  16. —–
    With these, we can provide a delegate to be called for our yield instruction test.

    yield return new WaitWhile(() => Time.realtimeSinceStartup < waitTime);

    Isn't this code generating an anonymous delegate? Means it allocates memory with every execution. I hope that's not real code found in Unity, as I prefer zero GC allocs. Sad enough that using yield already generates garbage, don't need even more of it.

    Otherwise it's another feature you can hardly use for periodically called code, unless you don't care about framerate hiccups caused by the GC kicking in every now and then.

    1. Its just an example, its not code in Unity.

  17. Is there a reason why a base class was used and not an interface?

    1. Well the base class does have a very simple implementation, we just override one part. There are 2 more functions that could be overridden so using an abstract class means we don’t need to implement the whole thing, just what we want to change.

      1. You could accomplish the same and not leak implementation details by making it an interface and then wrapping the user’s implementation in an internal class that tracks the state. This also avoids potential issues with inheritance hierarchies for us end users.

    2. This is just a helper class to make it easier to implement simple yield instructions. If you want flexibility or more control, you can now derive from IEnumerator (this is what CustomYieldCoroutine is actually doing, see my answers above).

  18. Thomas Mountainborn

    December 1, 2015 at 7:49 pm

    Very useful indeed, thanks for highlighting it. Any chance the devs could refactor “keepWaiting” to “KeepWaiting”? It is a property, after all.

    1. We would have to refactor the whole engine then, our properties start with lower case :)

    2. That would contradict to Unity’s own naming standards, although (which is requested by you) match those of .NET/Mono. I guess Unity guys prefer to stick to, well, Unity standards. Why they introduced their own standards back in the day is now history. There is no and cannot be any final solution about this question, as your code always contradicts either Unity standards, or .NET standards. Unless you invent a time machine, return to the past and change it, your request is meaningless and satisfying it would introduce more inconsistency. Cheers

  19. Sounds like WaitForSecondsRealtime should be implemented by default in the API.

    1. It now is ;)
      Should be out in a future release.

  20. This looks really cool, thanks for making a blogpost about it! Eventhough i try to read the changelog carefully this one slipped through, and its super useful.

  21. Your code example is clearing the list you are iterating over inside the for loop, so you will not be calling DestroyItem on all the items in the list. Looks like you want to clear the list after the for loop.

    1. Yes that’s strange. DestroyItem doesn’t actually do anything, its an empty virtual function so that explains why its been missed.

  22. Thanks Karl for sharing the new feature. It looks like it will be very useful.

    You have a small mistake in your post. 1 x 0.5 = 2 should be 1 / 0.5 = 2

    1. Ah nice catch, thanks.

  23. Matthew Wegnerr

    December 1, 2015 at 4:53 pm

    You should actually use Time.unscaledTime (or accumulate Time.unscaledDeltaTime).

    Using Time.realTimeSinceStartup will jump ahead unexpectedly if the player pauses the game by tabbing out…

    1. Good point

    2. In that case they should also add WaitForSecondsUnscaledTime and not replace the new WaitForSecondsRealtime

      1. “the new WaitForSecondsRealtime” is actually not a new built-in Unity feature but rather an example of how one would build a class inheriting from the new CustomYieldInstruction class (which is a new built-in Unity feature).

        1. Oh, I see what you mean. If they implemented WaitForSecondsRealtime may as well implement WaitForSecondsUnscaledTime in the API.

          I still get confused by Coroutines without the custom yield. :-)