How does MonoBehaviour.Invoke work under the hood?

I’m new to Unity and I would like to understand how MonoBehaviour.Invoke works under the hood.

Is this equivalent to something like this? (Except that instead of fixed “MethodToInvoke” we call an arbitrary method by its name using “GetMethod”)

public class Invoker : MonoBehaviour
{
    private float invokeDelay;
    private float startTime;
    private bool wasInvoked;

    void MyInvoke(float delay) {
        startTime = Time.fixedTime;
        wasInvoked = false;
        invokeDelay = delay;
    }


    void Update() {
        if (!wasInvoked && Time.fixedTime - startTime >= invokeDelay) {
            MethodToInvoke();
            wasInvoked = true;
        }
    }

    void MethodToInvoke() {
        // some code here
    }
}

Or is there something more advanced, like a queue for methods to invoke?

Is it safe to call Invoke inside the invoked function or will it cause infinite recursion and crush my app? Something like this:

public class Example : MonoBehaviour
{
    private void Start() {
        Invoke("MethodToInvoke", 1f);
    }

    private void MethodToInvoke() {

        // something useful, like spawning objects

        float randomDelay = Random.Range(1f, 5f);
        Invoke(MethodToInvoke, randomDelay);
    }
}

I would also like to understand the bigger picture, so a deep dive on how Unity works internally will be very very appreciated!

Eh, … Invoke() does so little, is so trivially reproducible, that I wouldn’t even bother using it if you’re that worried about it.

For instance, this tiny piece of code gets you basic Invoke() functionality that you control directly and explicitly:

https://gist.github.com/kurtdekker/0da9a9721c15bd3af1d2ced0a367e24e

Add a while(true) loop and you have InvokeRepeating()

Add a callback conditional delegate and you have InvokeRepeatingUntilTrue()

Not a useful pursuit. Anything not documented is prone to change.

Stick with what is documented, such as this:

Here is some timing diagram help:

https://docs.unity3d.com/Manual/ExecutionOrder.html

Remember you are not writing the app. The app is written and the engine is Unity. Your scripts are called at Unity’s convenience according to the above diagram.

Don’t write code that relies on any other promises or assumptions, or at least understand that you do so at your own peril.

Jump right in, try lots of stuff, see how things are usually done, and generally try to do things the same way, most of the time. It’s a big fun party in here! Unity is the best engine ever!

2 Likes

We don’t know the exact implementation because it calls a native function called InvokeDelayed. If I had to guess, I’d assume it’s just a flat collection of tuples with a timer and the callback. Repeating Invoke from within the invokee will only crash if there’s no delay. You should avoid Invoke entirely, partly because of the blackbox functionality and partly because relying on strings is fragile.

3 Likes