Error: some objects were not cleaned up when closing the scene

Hello,

When stopping playmode while playing in certain levels I get reproducably an error message in the console that some objects are not cleaned up. Unity is right, I found the problem. The question is how to fix it properly.

So I have a manager script in a singleon pattern to cover the most basic functions of the game. When playmode stops its OnDestroy() method is called. I have tons of other scripts accessing this manager script during normal execution. One has a call to the manager in its OnDestroy() method and when leaving playmode this is executed and - ups - the manager is already gone!

So is there a proper way to tell all other scripts doing its OnDestroy and as last script do OnDestroy of the manager script?

I already know about the definition of execution order at startup, the OnApplicationQuit() event and hooking into the Playmode change event.

As you see in my posted scripts accessing the instance of the manager script Services.cs during shutdown now prints the message “Services: Accessing while application is quitting.”, but it does not fix the problem of script execution order.

Thanks,
Chris

public class SingletonMono<T> : MonoBehaviour where T : MonoBehaviour
{
    protected static T instance;
    protected static bool applicationIsQuitting;

    public static T Instance
    {
        get
        {
            if (instance == null)
            {
                if (applicationIsQuitting)
                {
                    Debug.LogError($"Singleton: Accessing while application is quitting.");
                }
                Dbg.LogError($"Singleton: instance not set of type '{typeof(T).ToString()}'.");
            }
            return instance;
        }
    }

    protected virtual void Awake()
    {
        instance = this.gameObject.GetComponent<T>();
    }

    void OnDestroy()
    {
        instance = null;
        applicationIsQuitting = true;
    }
}
public class Services : SingletonMono<Services>
{

    public static new Services Instance
    {
        get
        {
            // attention: Normally the app is started with the Init scene with proper initialization.
            // In all other cases accessing the services leads to lazy loading of them.
            if (instance == null)
            {
                if (!applicationIsQuitting)
                {
                    Dbg.LogWarning($"Services instance not set. Try to instantiate services now.");
                    var loadedObject = Resources.Load("Services");
                    if (loadedObject != null)
                    {
                        Dbg.Log($"Services instantiated. Try to initialize services now.");
                        Instantiate(loadedObject, Vector3.zero, Quaternion.identity);
                    }
                    else
                    {
                        Dbg.LogError($"Services could not be loaded.");
                    }
                }
                else
                {
                    Debug.LogError($"Services: Accessing while application is quitting. Expect errors.");
                }
            }
            return instance as Services;
        }
    }

}

The problematic code is

public class SomeOtherScript : MonoBehaviour
{
        public void OnEnable()
        {
            Services.Instance.someMethod();  // works
        }

        public void OnDisable()
        {
            Services.Instance.someMethod();  // crash, service is already cleaned up
        }

}