What’s an Invoke or StartCoroutine between friends?
Warning this is my take on the subject, I didn’t write either of these things :)
I’ve been pondering the virtues of Unity Invoke vs. StartCoroutine and I couldn’t really find out much about how Invoke actually works. I know its signature;
Invoke(string name of method, float delay before running)
and that gives me some concerns as already I’m thinking that’s a late bound name to a method. But what is it doing behind the scenes?
The .net source code isn’t much help
It quickly vanishes into the internals of Unity.
StartCoroutine isn’t very helpful either, apart from we know it involves an IEnumerator
[MethodImpl(MethodImplOptions.InternalCall)]
private extern Coroutine StartCoroutineManaged2(IEnumerator enumerator);
So I ran a quick test to see how they work;
What I think we’re seeing is that both Invoke and StartCoroutine are handled by the same stage in Unity’s code processing; CoroutinesDelayedCalls. That says to me that they’re essentially going to work the same way with respect to the lifecycle. That’s good news. So what are the differences? It seems to come down to late-bound (Mono.JIT) vs IEnumerator. But there’s almost nothing in it, the Invoke is insignificantly slower and the IEnumerator causes one additional call (the end of enumerator). So it only seems to come down to your use and if you follow Unity recommendations (which is now to use StartCoroutine).
There are a couple of related points that I’d like to raise;
There is an oft held belief that Enumerators are a performance and alloc issue. I believe this goes back to a problem with earlier Mono implementations used in Unity. If you’re using a recent version of Unity you shouldn’t see such problems — unless your code is causing it ;)
Invoke relies in supplying a time based delay. In software, including Unity, it can be a dangerous assumption to rely on time. When a system is under stress things may not happen within a typical or expected time-frame, think carefully before relying on them.
Lastly, don’t get confused with Action.Invoke…that’s a completely different thing…perhaps another reason to stop using this variant of Invoke?