Reliable way to detect when the game starts playing on a ScriptableObject?

I am using a Scriptable Object architecture, and as part of it I need what Awake claims to do according to the documentation

“Awake is called as the ScriptableObject script starts. This happens as the game is launched and is similar to MonoBehavior.Awake.”

This doesn’t seem to be true when playing. I have breakpoints on the Awake function, and it gets called at random times in edit mode, and doesn’t get called when switching to play mode at all.

I tried using OnEnable instead, combined with a check of Application.IsPlaying because OnEnable gets called at random times in edit mode too, but at least this one does get called when starting play mode.

But here’s the funny thing:

        private void OnEnable()
        {
            Debug.Log("The game is " + (Application.isPlaying ? "playing" : "not playing"));
            if (Application.isPlaying)
            {
                LevelLoaded(null);
            }
        }

During the OnEnable call right after pressing the play button, Application.isPlaying is false, despite the game being in play mode. The above Debug log will print The game is not playing. It seems that the Application.isPlaying gets enabled after OnEnable is called.

At this point I have run out of ideas of ways I could get some kind of function call when the game starts.

If you have a architecture based on your scriptableObject, there is more information needet what you want todo with that architecture, load it? setup elements based on its information etc…

You cannot get reliable OnEnable/OnDisable calls on scriptable objects. They get called but it is not analogous to MonoBehaviors. ScriptableObject lifecycles differ in editor versus built application, so it is rather uselessly misleading. Avoid it.

Just put code you need in an OnEnable() on a Monobehavior and do what you need.

Here is some timing diagram help:

2 Likes

Yep, in the end I’ve put a “level manager” in each scene that notifies scriptable objects that need to initialise on game load or scene load… not ideal but that’s the only solution I can see

2 Likes

If you want to know more about ScriptableObject’s callback order then you should check out this post .

Another approach is to use EditorApplication.playModeStateChanged. After some tests, I see that this behaviour only happens in the editor, not in runtime, so I can do a #if UNITY_EDITOR and use playModeStateChanged.