FAQ

Q: Does MEC have a segment for WaitForEndOfFrame?

It is not implemented in MEC Free, but there is a segment for it in MEC Pro.

NOTE: There is some confusion about what WaitForEndOfFrame actually does. When you just want to yield until the next frame then WaitForEndOfFrame is not really an ideal command, it’s better to use “yield return Timing.WaitForOneFrame;”. Many people use WaitForEndOfFrame when using Unity’s coroutines because it’s the closest thing they can find to WaitForOneFrame in Unity’s default coroutines and they don’t realize that it can cause subtle issues. Now with MEC you can use explicit variable names if you want without creating the potential for the visual glitches described below.

This page has a graph that shows the timing for each frame. As the graph shows, WaitForEndOfFrame executes after all rendering has finished. If you were to use that call in a Unity coroutine to move a button across the screen then the button would always be drawn in the position you had set it to on the previous frame. In most cases the frame rate is high enough that you wouldn’t notice the difference visually, but this practice can cause subtle visual glitches that are difficult to explain or debug.

For instance, if you had an enemy ship and an “enemy ship explodes” animation it would be common practice to call Destroy on the enemy ship object and Instantiate the explosion animation at the same time. However, if you did this in a coroutine that had been calling WaitForEndOfFrame then the user might see what appears to be the ship blinking for an instant before exploding.

Also, canvases normally recalculate just after the Update segment, so Unity’s WaitForEndOfFrame can have a serious negative effect on performance if you use it wrong because it will cause the canvas to have to recalculate twice per frame.

Q: Does MEC have a function for StopCoroutine?

A: Yes. It’s called Timing.KillCoroutines(). It can either take a handle to a coroutine that was returned by a previous Timing.RunCoroutine command, or it can take a tag.

NOTE: KillCoroutine is for stopping a coroutine function from a different function. If you want to end a coroutine from inside that coroutine’s function then the best command to use is “yield break;”, which is the equivalent of calling “return;” in any other function.

Q: Does MEC have a function for StopAllCoroutines?

A: Yes. Timing.KillCorutines(). You can also use Timing.PauseCoroutines() and Timing.ResumeCoroutines() if you would rather stop everything temporarily.

Q: Does MEC have a function to yield one coroutine until another one finishes?

A: Yes. From inside the coroutine that you want to hold you call “yield return Timing.WaitUntilDone(coroutineHandle);” The handle is returned whenever you call Timing.RunCoroutine.

NOTE: The handle must be the same variable that you originally returned by RunCoroutine. If you attempt to create a new instance of the handle then the WaitUntilDone function will fail to find a match.

Q: Does MEC completely remove GC allocs?

A: No. MEC removes all per-frame GC allocs. (unless you allocate memory on the heap inside of your coroutine, but MEC has no control over that.) When a coroutine is first created the function pointer and any variables you pass into it are put on the heap and eventually have to be cleaned up by the garbage collector. This unavoidable allocation happens in both Unity’s coroutines and MEC coroutines. MEC coroutines do allocate less garbage on average than Unity coroutines.

Q: Are MEC coroutines always more memory efficient than Unity coroutines, or is it only in select cases?

A: MEC coroutines produce less GC allocation than Unity coroutines do in all cases, except if you large strings and assign them as the tag for a coroutine.

Q: Reduced GC allocs are great, but are there any other advantages to MEC coroutines over Unity’s coroutines.

A: The MEC infrastructure runs about twice as fast as Unity’s coroutine infrastructure. For more information on that please watch the video on the performance of MEC vs Unity coroutines, which is linked to on the asset’s page.

Unity’s coroutines are attached to the object that you started them on while MEC uses a central object to run all its processes. That means that the following three things are true:

  1. Unity’s coroutines won’t start if the current object is disabled. MEC coroutines don’t care.
  2. If you disable a GameObject then all of the Unity coroutines that are attached to it will quit running (they do not resume on re-enable.) MEC coroutines don’t do this unless you explicitly tell them to.
  3. If the GameObject that you started a Unity coroutine on is destroyed then all the attached coroutines will also be killed. MEC coroutines also don’t do this.

MEC coroutines allow you to create coroutine groups, which give you the ability to pause/resume or destroy whole groups of coroutines at the same time. Unity’s coroutines don’t allow you to pause and resume coroutines from the outside, and Unity’s coroutines are always grouped by the gameObject that they were started on.

Lastly, MEC coroutines allow you to run the coroutine in the LateUpdate or SlowUpdate segment if you want to. MEC Pro has even more segments.

Q: I heard that it was slow to have a bunch of Update functions in my scripts, but I like update functions. Can I use MEC to make my Update functions faster?

A: Yes. You just need to follow these three steps:

  1. Add the following function to any utility class. (If you don’t already have one then just make a new static class called Util and put this function in it.)
  2. public static IEnumerator<float> _EmulateUpdate(System.Action func, MonoBehaviour scr)
    {
        yield return Timing.WaitForOneFrame;
        while (scr.gameObject != null)
        {
            if (scr.gameObject.activeInHierarchy && scr.enabled)
                func();
    
                yield return Timing.WaitForOneFrame;
        }
    }
    
  3. In every class where you want to use update more efficiently you need to change the name of the Update function to something other than “Update” (you can name it anything, I’ll assume you named it “MyUpdate”).
  4. Run the above coroutine at the end of each class you changed’s Start function, like this:
Timing.RunCoroutine(Util._EmulateUpdate(MyUpdate, this));