Search Unity

Feedback NetworkManager should have a OnShutdown event

Discussion in 'Netcode for GameObjects' started by CodeSmile, Oct 10, 2022.

  1. CodeSmile

    CodeSmile

    Joined:
    Apr 10, 2014
    Posts:
    5,937
    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.
     
  2. CodeSmile

    CodeSmile

    Joined:
    Apr 10, 2014
    Posts:
    5,937
    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:

    Code (CSharp):
    1.         private void Update()
    2.         {
    3.             if (IsClient && IsServer == false && NetworkManager.IsConnectedClient == false)
    4.             {
    5.                 LoadSceneNonNetworked();
    6.             }
    7.         }
    This works for me because IsClient is set to false when NetworkManager.Shutdown() ran, and it's also false before joining.
     
    pradotech likes this.
  3. pradotech

    pradotech

    Joined:
    Oct 17, 2019
    Posts:
    35
    Nice workaround, I just adapted to a Coroutine like this:
    Code (CSharp):
    1.     private IEnumerator LoadMenuDelayed()
    2.     {
    3.         while (NetworkManager.Singleton.IsClient || NetworkManager.Singleton.IsServer || NetworkManager.Singleton.IsConnectedClient)
    4.             yield return null;
    5.  
    6.         SceneCore.Instance.LoadMainMenu();
    7.     }
     
    CodeSmile likes this.
  4. CodeSmile

    CodeSmile

    Joined:
    Apr 10, 2014
    Posts:
    5,937
    DRY principle applied:
    Code (CSharp):
    1.     private IEnumerator LoadMenuDelayed()
    2.     {
    3.         var netMan = NetworkManager.Singleton;
    4.         while (netMan.IsClient || netMan.IsServer || netMan.IsConnectedClient)
    5.             yield return null;
    6.         SceneCore.Instance.LoadMainMenu();
    7.     }
     
  5. Lasko1

    Lasko1

    Joined:
    Dec 30, 2021
    Posts:
    5
    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:

    Code (CSharp):
    1. public class ExtendedNetworkManager : NetworkManager
    2. {
    3.     public static event EventHandler OnShutdown;
    4.  
    5.     public static void NotifiedShutdown(object sender)
    6.     {
    7.         Singleton.Shutdown();
    8.         OnShutdown?.Invoke(sender, EventArgs.Empty);
    9.     }
    10. }
    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.
     
    Last edited: Nov 2, 2022
  6. henrique11

    henrique11

    Joined:
    Jan 1, 2020
    Posts:
    3
    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.
    Code (CSharp):
    1. OnClientDisconnectCallback += OnDisconnected;
    Code (CSharp):
    1.     private void OnDisconnected(ulong id)
    2.     {
    3.         if(id == 0){ // In my case it is always 0
    4.             // Load Menu Scene or something
    5.         }
    6.     }
     
  7. NoelStephens_Unity

    NoelStephens_Unity

    Unity Technologies

    Joined:
    Feb 12, 2022
    Posts:
    259
    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.