'How to unsubscribe from an event inside of the gamemanager?

In my GameManager script I have a delegate. In my Door script, I subscribe to this delegate. I've tried unsubscribing from it in both the OnDisable and OnDestroy methods in the Door script. In both cases, I get an error when I stop running the game in the editor:

Some objects were not cleaned up when closing the scene. (Did you spawn new GameObjects from OnDestroy?)

Using Debug.Log, I found out that this is because the GameManager will always be destroyed before the Door script. Even if I do a null check inside either the OnDisable or OnDestroy of the Door script to see if the GameManager is null, I get the same error

if (GameManager.Instance)
{
    GameManager.Instance.OnAllEnemiesKilled -= OpenDoor;
}

Somebody told me that I don't need to unsubscribe from it, as the delegate will automatically become null when the Door object is destroyed, but that's not true. During runtime, after the Door is destroyed, my update loop inside of the GameManager is still printing that the delegate has one subscriber: the Door.



Solution 1:[1]

As Lece pointed out, I'm spawning a new singleton when I call GameManager.Instance. Rather than creating a static bool to remedy the problem however, I replaced if (_instance == null) with if ((object)_instance == null) inside my Instance getter and it solved the problem. This is because, while the object is destroyed in the native code, it still exists in the managed code. So I'm now referencing it in the managed world. Moreover, Unity makes it so that when an object is destroyed in native code, its value in managed code will still return null.

Solution 2:[2]

I suspect you're spawning a new singleton when you call GameManager.Instance after it's been destroyed? If so, do something like this instead:

public class GameManager : MonoBehaviour
{
    public static GameManager Instance
    {
        get
        {
            if (isDestroyed) return null;

            // Your spawn logic...
        }
    }

    static bool isDestroyed;

    void OnDestroy()
    {
        isDestroyed = true;
    }
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2