NetworkManager should have a OnShutdown event

NetworkManager has no built-in event that occurs on shutdown.

I added a disconnect button for clients and within the GUI I just call NetworkManager.Singleton.Shutdown(). It works, but ... other systems don't get to know about that. For instance, I may want to load a scene on disconnect in a different subsystem.

Since OnClientDisconnected isn't called in that case (due to the client logically disconnecting itself) I currently have no other option than to create my own event delegate to forward the disconnect/shutdown request by user action. Not much extra work but really something NetworkManager should already provide ie an OnShutdown event.

Found a workaround that works in my case.

In the Scene loading NetworkBehaviour I added an Update() method that checks if we are a client (non-host) but not connected:

        private void Update()
        {
            if (IsClient && IsServer == false && NetworkManager.IsConnectedClient == false)
            {
                LoadSceneNonNetworked();
            }
        }

This works for me because IsClient is set to false when NetworkManager.Shutdown() ran, and it's also false before joining.

1 Like

Nice workaround, I just adapted to a Coroutine like this:

    private IEnumerator LoadMenuDelayed()
    {
        while (NetworkManager.Singleton.IsClient || NetworkManager.Singleton.IsServer || NetworkManager.Singleton.IsConnectedClient)
            yield return null;

        SceneCore.Instance.LoadMainMenu();
    }
1 Like

DRY principle applied:

    private IEnumerator LoadMenuDelayed()
    {
        var netMan = NetworkManager.Singleton;
        while (netMan.IsClient || netMan.IsServer || netMan.IsConnectedClient)
            yield return null;
        SceneCore.Instance.LoadMainMenu();
    }

Found this thread because of the exact same problem I'm having.

To avoid performing a check every frame, I created a new "ExtendedNetworkManager" class that inherits from NetworkManager:

public class ExtendedNetworkManager : NetworkManager
{
    public static event EventHandler OnShutdown;

    public static void NotifiedShutdown(object sender)
    {
        Singleton.Shutdown();
        OnShutdown?.Invoke(sender, EventArgs.Empty);
    }
}

I replaced the NetworkManager component on my NetworkManager GameObject with the new ExtendedNetworkManager component.

Then, instead of calling NetworkManager.Singleton.Shutdown(), I use ExtendedNetworkManager.NotifiedShutdown(this). Observers subscribe to ExtendedNetworkManager.OnShutdown.

I would love a native OnShutdown event though.

If you know the id of the Host, you can use the OnClientDisconnectCallback. When the Host leaves or closes the Server, that event will be fired on all connected Clients.

OnClientDisconnectCallback += OnDisconnected;
    private void OnDisconnected(ulong id)
    {
        if(id == 0){ // In my case it is always 0
            // Load Menu Scene or something
        }
    }

You can always have other components (etc) subscribe to:
NetworkManager.OnServerStopped

This is invoked when the server/host is completely shutdown.

Alternately, if you always run as a host (i.e. not a dedicated server) or you want the same kind of functionality on the client side you can subscribe to:

NetworkManager.OnClientStopped

Take Note: If you are running a host, then both OnServerStopped and OnClientStopped will be invoked. Just keep that in mind in the event you subscribe to both events (i.e. be cautious not to invoke the same functionality more than once on the host side).

For reference, here are the NetworkManager's full set of events you can subscribe to.