How to call Update() from a class that's not inheriting from MonoBehaviour?

Hi. I’m pretty new to scripting and I realized while I was creating my state machine that my StateMachine class is inheriting from ScriptableObject (because I don’t want it to be attached to a particular gameobject). And my PlayerStateMachine class is inheriting from the StateMachine class. I wanted to know if there was a way to call the Update() function even if that class is not inheriting from MonoBehaviour. Any help would be appreciated.

GravStateMachine.cs is my StateMachine class
PlayerStateMachine.cs is my PlayerStateMachine class

2926745–216336–GravStateMachine.cs (923 Bytes)
2926745–216337–PlayerStateMachine.cs (1.94 KB)

Please post code in [

 tags![/URL]

The easiest thing is to just have some MonoBehaviour that's responsible for calling Update on all of your scriptables.

](Using code tags properly - Unity Engine - Unity Discussions)

You can have a singleton MonoBehaviour that calls the Update’s for non-MonoBehaviour objects via an event; i.e:

using UnityEngine;

public class UpdateCaller : MonoBehaviour
{
    private static UpdateCaller instance = null;
    public static System.Action OnUpdate;
  
    void Awake()
    {
        if( instance == null )
        {
            instance = this;
            DontDestroyOnLoad( this );
        }
        else if( this != instance )
            Destroy( this );
    }
  
    void Update()
    {
        if( OnUpdate != null )
            OnUpdate();
    }
}

Then:

public class NonMonoBehaviourClass
{
    public NonMonoBehaviourClass()
    {
        UpdateCaller.OnUpdate += Update;
    }
  
    ~NonMonoBehaviourClass()
    {
        UpdateCaller.OnUpdate -= Update;
    }
  
    void Update()
    {
  
    }
}

P.S: Don’t forget to add UpdateCaller as a component to an empty GameObject.

6 Likes

If you’re going to have a singleton MonoBehaviour, it’s a lot easier to have it be lazy:

public class UpdateCaller : MonoBehaviour {
    private static UpdateCaller instance;
    public static void AddUpdateCallback(Action updateMethod) {
        if (instance == null) {
            instance = new GameObject("[Update Caller]").AddComponent<UpdateCaller>();
        }
        instance.updateCallback += updateMethod;
    }

    private Action updateCallback;

    private void Update() {
        updateCallback();
    }
}

This means that you don’t have to remember to add a script to every scene you use. If your prefabs are relying on that UpdateCaller existing, that will make testing those prefabs a lot easier too.

As an added bonus, you get rid of the null-check. I haven’t added any unsubscribe functionality, but you should add that if you need it (if your ScriptableObjects that use this ever get destroyed). You’ll also have to make decisions about if the UpdateCaller should be set to DontDestroyOnLoad or not, depending on if your Scriptables live between scenes.

3 Likes