How to call Monobehaviour methods in normal C# script?

Eg. I need to call StartCoroutine() in a C# script that does not inherit from Monobehaviour.

What is the best way to call a Monobehaviour method in a normal C# script?

One way I could think of is to define the required functionality (that involve the StartCoroutine) in a Monobehaviour inherited C# file and then reference it in the C# script (that does not inherit from Monobehaviour) via a public field.

Thanks!

MonoBehaviour.StartCoroutine() is public, so you can call it from any class. All you need is a reference to a monobehaviour. You don’t need to do any plumbing to get it working.

By “reference to a monobehaviour”, do you mean

MonoBehaviour MB = new MonoBehaviour(); and then get the StartCoroutine() with MB.StartCoroutine() ?

Thanks!

That is exactly what you ened to do.

what what what, no. That won’t work!

MonoBehaviours needs to be attached to a gameObject. Creating a new MonoBehaviour like that will cause Unity to throw errors at you and not do anything.

The magic methods on MonoBehaviour are called by the engine on all MonoBehaviours in the scene when the engine sees fit to do so. If you want to run a coroutine, you’ll need some MonoBehaviour to start it on. But you’ll have to find/create a MonoBehaviour in the scene.

We use a coroutine runner singleton to handle needing coroutines to happen from outside of a MonoBehaviour (or if the coroutine needs to live longer than the MB). The setup is pretty easy, here’s a simplified version:

public static class StaticCoroutine {
    private class CoroutineHolder : MonoBehaviour { }

    //lazy singleton pattern. Note that I don't set it to dontdestroyonload - you usually want corotuines to stop when you load a new scene.
    private static CoroutineHolder _runner;
    private static CoroutineHolder runner {
        get {
            if (_runner == null) {
                _runner = new GameObject("Static Corotuine Runner").AddComponent<CoroutineHolder>();
            }
            return _runner;
        }
    }

    public static void StartCoroutine(IEnumerator corotuine) {
        runner.StartCoroutine(corotuine);
    }
}

So you use it by doing:

StaticCoroutine.StartCorotuine(MyCorotuine());

Simple stuff! You can’t start a coroutine with a string in this way, but starting a coroutine with a string gets people killed, so you should avoid that.

If you want Update/Start/Awake on a non-monobehaviour, that doesn’t really make any sense! I guess you could set up a similar static runner object and create things like an Update-event you could subscribe to? idk why you’d do that, though.

6 Likes

amen to that

2 Likes

A little late here, but I was wondering if you know why it’s possible to create a non-static class inside of a static class. I thought everything inside of a static class had to be static as well. I find it interesting that even that class can be added as a component to a GameObject. Thanks for sharing!

If you had had a non-static field or method inside of a static class, there would be no way to access it, as they need an object instance to be accessed. That’s why you can’t have them there.

A nested class, on the other hand, can be accessed just fine, so it’s allowed.