From e6693e90ccf3f0dc68e2626de3bfda3ad27d072d Mon Sep 17 00:00:00 2001 From: Emma Date: Mon, 2 Nov 2026 10:47:23 -0500 Subject: [PATCH] fix: handle NetworkManager Awake being overridden --- .../Runtime/Core/NetworkManager.cs | 27 ++++++++++-- .../Tests/Runtime/NetworkManagerTests.cs | 41 +++++++++++++++++++ 2 files changed, 65 insertions(+), 3 deletions(-) diff --git a/com.unity.netcode.gameobjects/Runtime/Core/NetworkManager.cs b/com.unity.netcode.gameobjects/Runtime/Core/NetworkManager.cs index 25b86e3da0..508180ea63 100644 --- a/com.unity.netcode.gameobjects/Runtime/Core/NetworkManager.cs +++ b/com.unity.netcode.gameobjects/Runtime/Core/NetworkManager.cs @@ -1071,7 +1071,7 @@ public void SetSingleton() OnSingletonReady?.Invoke(); } - private void Awake() + protected virtual void Awake() { if (Log == null) { @@ -1088,7 +1088,7 @@ private void Awake() OnInstantiated?.Invoke(this); } - private void OnEnable() + protected virtual void OnEnable() { if (RunInBackground) { @@ -1337,6 +1337,11 @@ private bool CanStart(StartType type) /// returns true if started in server mode successfully; otherwise false public bool StartServer() { + if (Log == null) + { + Log = new ContextualLogger(this, false); + Log.Warning(new Context(LogLevel.Normal, "No logger defined. Ensure base.Awake() and base.OnEnable is called in any derived NetworkManager classes.")); + } Log.CaptureFunctionCall(); if (!CanStart(StartType.Server)) @@ -1397,6 +1402,11 @@ public bool StartServer() /// (/) returns true if started in client mode successfully. public bool StartClient() { + if (Log == null) + { + Log = new ContextualLogger(this, false); + Log.Warning(new Context(LogLevel.Normal, "No logger defined. Ensure base.Awake() and base.OnEnable is called in any derived NetworkManager classes.")); + } Log.CaptureFunctionCall(); if (!CanStart(StartType.Client)) @@ -1450,6 +1460,11 @@ public bool StartClient() /// (/) returns true if started in host mode successfully. public bool StartHost() { + if (Log == null) + { + Log = new ContextualLogger(this, false); + Log.Warning(new Context(LogLevel.Normal, "No logger defined. Ensure base.Awake() and base.OnEnable is called in any derived NetworkManager classes.")); + } Log.CaptureFunctionCall(); if (!CanStart(StartType.Host)) @@ -1752,8 +1767,14 @@ private void OnApplicationQuit() } // Note that this gets also called manually by OnSceneUnloaded and OnApplicationQuit - private void OnDestroy() + protected virtual void OnDestroy() { + if (Log == null) + { + Log = new ContextualLogger(this, false); + Log.Warning(new Context(LogLevel.Normal, "No logger defined. Ensure base.Awake() and base.OnEnable is called in any derived NetworkManager classes.")); + } + try { ShutdownInternal(); diff --git a/testproject/Assets/Tests/Runtime/NetworkManagerTests.cs b/testproject/Assets/Tests/Runtime/NetworkManagerTests.cs index ccf46cb61c..e1262bd920 100644 --- a/testproject/Assets/Tests/Runtime/NetworkManagerTests.cs +++ b/testproject/Assets/Tests/Runtime/NetworkManagerTests.cs @@ -198,4 +198,45 @@ private void OnServerStopped(bool obj) m_ServerNetworkManager.Shutdown(); } } + + internal class DerivedNetworkManagerTests + { + private class TestNetworkManager : NetworkManager + { + public void Awake() { } + public void OnEnable() { } + } + + [UnityTest] + public IEnumerator ValidateDerivedNetworkManager() + { + var gameObject = new GameObject("TestNetworkManager"); + var server = gameObject.AddComponent(); + var mockTransport = server.gameObject.AddComponent(); + server.NetworkConfig ??= new NetworkConfig(); + server.NetworkConfig.NetworkTransport = mockTransport; + var client = Object.Instantiate(server); + + var isListening = server.StartServer(); + Assert.That(isListening, Is.True, "Server failed to start!"); + + client.StartClient(); + + var timeoutHelper = new TimeoutHelper(); + yield return NetcodeIntegrationTest.WaitForConditionOrTimeOut(() => client.IsListening, timeoutHelper); + Assert.That(timeoutHelper.TimedOut, Is.False, "Client timed out waiting to connect!"); + + Object.Destroy(client.gameObject); + + server.Shutdown(); + timeoutHelper = new TimeoutHelper(); + yield return NetcodeIntegrationTest.WaitForConditionOrTimeOut(() => !server.IsListening, timeoutHelper); + Assert.That(timeoutHelper.TimedOut, Is.False, "Timed out waiting for server to shutdown!"); + + isListening = server.StartHost(); + Assert.That(isListening, Is.True, "Host failed to start!"); + + Object.Destroy(gameObject); + } + } }