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.
2 Likes
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();
}
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.
1 Like
I have found when writing a routine to disconnect from a networked game session and then immediately reconnect that NetworkManager.OnServerStopped is not sufficient to indicate when the server is fully shutdown, as further shutdown work continues after this event is fired.
If I attempt to call NetworkManager.Singleton.StartServer after this event has been fired, several errors are thrown and the server is left in a broken state. If I instead wait for NetworkManager.NetworkTickSystem to be set to null, which is the very last thing that NetworkManager.ShutdownInternal does before shutdown is completed, restarting the server after this point succeeds and networking works as normal.
I am using NGO v1.11.0, but the shutdown routine in NGO v2.0.0 looks to be very similar/identical
Are you calling StartServer inside the OnServerStopped event as I remember seeing something similar. I think it’s set up this way with the event called part-way through shutdown to allow clean up on the user side before full shutdown. I vaguely remember there being a post about this somewhere but I can’t find it.
That is correct, if you are rapidly reconnecting then you would need to/want to let the rest of this code:
// In the event shutdown is invoked within OnClientStopped or OnServerStopped, set it to false again
m_ShuttingDown = false;
// Reset the client's roles
ConnectionManager.LocalClient.SetRole(false, false);
// This cleans up the internal prefabs list
NetworkConfig?.Prefabs?.Shutdown();
// Reset the configuration hash for next session in the event
// that the prefab list changes
NetworkConfig?.ClearConfigHash();
// Time & tick systems should be the last system shutdown so other systems
// can unsubscribe from tick updates and such.
NetworkTimeSystem?.Shutdown();
NetworkTickSystem = null;
get executed within that call stack before immediately starting a new session.
Typically a coroutine that yield returns null and then reconnects/starts a session will do the trick.
Just to add, it may not be a post I remember as I found the same info here.
Thanks @cerestorm, that is effectively what I was doing, yes. Thanks for the link to the GitHub discussion!
@NoelStephens_Unity, thanks for confirming! I see in the linked GitHub issue, you suggested adding a NetworkManager.ShutdownComplete event to avoid the need to write additional logic to detect when a shutdown is fully completed. I think that would be a very useful and worthwhile addition in a future release of NGO 
Not sure if this is useful, but there will be two new static events you can register for in NetworkManager (v2 only):
NetworkManager.OnInstantiated
NetworkManager.OnDestroying
It doesn’t completely resolve the issue if you want to re-use the same instance, but if you are destroying and recreating then it does… heh… but I still intend on improving that… really there should be states that it sets and you can subscribe to changes in state…
Need to wiggle that into a near future update…
1 Like