You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
There’s no single event that fires once when networking starts, regardless of mode
Currently you need to handle both OnServerStarted and OnClientConnectedCallback, which leads to redundant or missing calls depending on the mode (client/server)
Using per-connection callbacks for this is unreliable, and managing timing around the singleton or validation properties(e.g IsListening) adds unnecessary complexity
Unless i am missing something, to me this dont feels right
Current workflow
The current workaround is using coroutines or polling to wait until the singleton exists and the NetworkManager is listening.
This adds overhead and makes initialization logic fragile, even more for singleplayer sessions where the code may keep waiting forever as no connections are made
Example (based on forums suggestions):
voidOnEnable(){StartCoroutine(SubscribeToNetworkManagerEvents());}IEnumeratorSubscribeToNetworkManagerEvents(){yieldreturnnewWaitUntil(()=>NetworkManager.Singleton);//This is fragile, and may add other problems, and no mention to cancelationsNetworkManager.Singleton.OnClientConnectedCallback+=OnClientConnectedCallback;//called on clients but unclear about standalone serverNetworkManager.Singleton.OnServerStarted+=OnServerStarted;//never called on non host client}voidOnDestroy(){if(NetworkManager.Singleton){NetworkManager.Singleton.OnClientConnectedCallback-=OnClientConnectedCallback;NetworkManager.Singleton.OnServerStarted-=OnServerStarted;}initialized=false;}voidOnClientConnectedCallback(parameters){RegisterMessageHandler();}voidOnServerStarted(parameters){RegisterMessageHandler();}boolinitialized;//Both on client connected callback and server started calls this other methodvoidRegisterMessageHandler(){if(initialized)return;//For exampleNetworkManager.Singleton.CustomMessagingManager.RegisterNamedMessageHandler("a",B);// In this case, Singleton can be null and CustomMessagingManager also can be null, thats why we need the yieldinitialized=true;}
These yields are required only because there is no dedicated lifecycle event indicating when the NetworkManager and its subsystems (like CustomMessagingManager) are fully initialized
As result, developers must manually simulate this missing initialization phase using coroutines or polling, which makes code more complex
Posible solution
Add new public static Action<NetworkManager> OnNetworkStarted event to NetworkManager Triggered once when the network stack has been initialized and the transport is ready, regardless of whether it’s running as server, client, or host.
Passing the Network manager initialized (as after working on the last pull request, i saw on the tests part and other parts of code might exist more than one NetworkManager)
This would change the workflow to a much more convenient one like this
While NetworkBehaviour.OnNetworkSpawn can be used for components, this event would support use cases where no scene objects are involved (e.g ScriptableObjects or systems initialized outside scene contexts). It provides a clean, unified hook for all modes.
This change would mostly take 2 lines
public static Action<NetworkManager> OnNetworkStarted on NetworkManager class
OnNetworkStarter?.Invoke(This); at the very end of NetworkManager's internal void Initialize(bool server) method
It only may cause problems on having it static with the editor reloading feature, but that could be arranged cleaning the event with the [RuntimeInitializeOnLoadAttribute]
The problem
There’s no single event that fires once when networking starts, regardless of mode
Currently you need to handle both OnServerStarted and OnClientConnectedCallback, which leads to redundant or missing calls depending on the mode (client/server)
Using per-connection callbacks for this is unreliable, and managing timing around the singleton or validation properties(e.g IsListening) adds unnecessary complexity
Unless i am missing something, to me this dont feels right
Current workflow
The current workaround is using coroutines or polling to wait until the singleton exists and the NetworkManager is listening.
This adds overhead and makes initialization logic fragile, even more for singleplayer sessions where the code may keep waiting forever as no connections are made
Example (based on forums suggestions):
Posible solution
Add new
public static Action<NetworkManager> OnNetworkStartedevent to NetworkManagerTriggered once when the network stack has been initialized and the transport is ready, regardless of whether it’s running as server, client, or host.
Passing the Network manager initialized (as after working on the last pull request, i saw on the tests part and other parts of code might exist more than one NetworkManager)
This would change the workflow to a much more convenient one like this
Note
While
NetworkBehaviour.OnNetworkSpawncan be used for components, this event would support use cases where no scene objects are involved (e.g ScriptableObjects or systems initialized outside scene contexts). It provides a clean, unified hook for all modes.This change would mostly take 2 lines
public static Action<NetworkManager> OnNetworkStartedon NetworkManager classOnNetworkStarter?.Invoke(This);at the very end of NetworkManager'sinternal void Initialize(bool server)methodIt only may cause problems on having it static with the editor reloading feature, but that could be arranged cleaning the event with the
[RuntimeInitializeOnLoadAttribute]