Search Unity

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

Discussion in 'Scripting' started by Nalaria, Aug 4, 2020.

  1. Nalaria

    Nalaria

    Joined:
    Jan 25, 2018
    Posts:
    7
    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:

    Code (CSharp):
    1.         private void OnEnable()
    2.         {
    3.             Debug.Log("The game is " + (Application.isPlaying ? "playing" : "not playing"));
    4.             if (Application.isPlaying)
    5.             {
    6.                 LevelLoaded(null);
    7.             }
    8.         }

    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.
     
  2. Terraya

    Terraya

    Joined:
    Mar 8, 2018
    Posts:
    646
  3. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,745
    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:

    https://docs.unity3d.com/Manual/ExecutionOrder.html
     
    Jamisco and april_4_short like this.
  4. Nalaria

    Nalaria

    Joined:
    Jan 25, 2018
    Posts:
    7
    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
     
    Jamisco and Kurt-Dekker like this.
  5. Long2904

    Long2904

    Joined:
    May 13, 2019
    Posts:
    81
    If you want to know more about ScriptableObject's callback order then you should check out this post.
     
  6. Long2904

    Long2904

    Joined:
    May 13, 2019
    Posts:
    81
    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.