diff --git a/com.unity.netcode.gameobjects/CHANGELOG.md b/com.unity.netcode.gameobjects/CHANGELOG.md index 99cd9d24c5..049891c6b0 100644 --- a/com.unity.netcode.gameobjects/CHANGELOG.md +++ b/com.unity.netcode.gameobjects/CHANGELOG.md @@ -20,12 +20,16 @@ Additional documentation and release notes are available at [Multiplayer Documen ### Changed -## [1.5.2] - 2023-07-24 +## [1.6.0] - 2023-08-09 ### Added +- Added a protected virtual method `NetworkTransform.OnInitialize(ref NetworkTransformState replicatedState)` that just returns the replicated state reference. + ### Fixed +- Fixed issue where invoking `NetworkManager.Shutdown` within `NetworkManager.OnClientStopped` or `NetworkManager.OnServerStopped` would force `NetworkManager.ShutdownInProgress` to remain true after completing the shutdown process. (#2661) +- Fixed issue where ARMv7 Android builds would crash when trying to validate the batch header. (#2654) - Fixed issue with client synchronization of position when using half precision and the delta position reaches the maximum value and is collapsed on the host prior to being forwarded to the non-owner clients. (#2636) - Fixed issue with scale not synchronizing properly depending upon the spawn order of NetworkObjects. (#2636) - Fixed issue position was not properly transitioning between ownership changes with an owner authoritative NetworkTransform. (#2636) diff --git a/com.unity.netcode.gameobjects/Runtime/Core/NetworkManager.cs b/com.unity.netcode.gameobjects/Runtime/Core/NetworkManager.cs index 03076e657e..7bcedfdcbf 100644 --- a/com.unity.netcode.gameobjects/Runtime/Core/NetworkManager.cs +++ b/com.unity.netcode.gameobjects/Runtime/Core/NetworkManager.cs @@ -1013,6 +1013,9 @@ internal void ShutdownInternal() OnServerStopped?.Invoke(ConnectionManager.LocalClient.IsClient); } + // 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); diff --git a/com.unity.netcode.gameobjects/package.json b/com.unity.netcode.gameobjects/package.json index 936b298beb..d4952986c0 100644 --- a/com.unity.netcode.gameobjects/package.json +++ b/com.unity.netcode.gameobjects/package.json @@ -2,7 +2,7 @@ "name": "com.unity.netcode.gameobjects", "displayName": "Netcode for GameObjects", "description": "Netcode for GameObjects is a high-level netcode SDK that provides networking capabilities to GameObject/MonoBehaviour workflows within Unity and sits on top of underlying transport layer.", - "version": "1.5.2", + "version": "1.6.0", "unity": "2020.3", "dependencies": { "com.unity.nuget.mono-cecil": "1.10.1", diff --git a/testproject/Assets/Tests/Runtime/NetworkManagerTests.cs b/testproject/Assets/Tests/Runtime/NetworkManagerTests.cs index 90d3c74b1a..277e8f8836 100644 --- a/testproject/Assets/Tests/Runtime/NetworkManagerTests.cs +++ b/testproject/Assets/Tests/Runtime/NetworkManagerTests.cs @@ -1,4 +1,5 @@ using System.Collections; +using System.Linq; using NUnit.Framework; using Unity.Netcode; using Unity.Netcode.TestHelpers.Runtime; @@ -40,12 +41,15 @@ public NetworkManagerTests(UseSceneManagement useSceneManagement) private void OnClientConnectedCallback(NetworkObject networkObject, int numberOfTimesInvoked, bool isHost, bool isClient, bool isServer) { - m_NetworkObject = networkObject; - m_NetworkObjectWasSpawned = networkObject.IsSpawned; - m_NetworkBehaviourIsHostWasSet = isHost; - m_NetworkBehaviourIsClientWasSet = isClient; - m_NetworkBehaviourIsServerWasSet = isServer; - m_NumberOfTimesInvoked = numberOfTimesInvoked; + if (networkObject != null) + { + m_NetworkObject = networkObject; + m_NetworkObjectWasSpawned = networkObject.IsSpawned; + m_NetworkBehaviourIsHostWasSet = isHost; + m_NetworkBehaviourIsClientWasSet = isClient; + m_NetworkBehaviourIsServerWasSet = isServer; + m_NumberOfTimesInvoked = numberOfTimesInvoked; + } } private bool TestComponentFound() @@ -96,22 +100,86 @@ public void ValidateHostSettings() Assert.IsTrue(m_NetworkBehaviourIsServerWasSet, $"IsServer was not true when OnClientConnectedCallback was invoked!"); } + public enum ShutdownChecks + { + Server, + Client + } + + protected override void OnNewClientCreated(NetworkManager networkManager) + { + networkManager.NetworkConfig.EnableSceneManagement = m_EnableSceneManagement; + foreach (var prefab in m_ServerNetworkManager.NetworkConfig.Prefabs.Prefabs) + { + networkManager.NetworkConfig.Prefabs.Add(prefab); + } + base.OnNewClientCreated(networkManager); + } + /// /// Validate shutting down a second time does not cause an exception. /// [UnityTest] - public IEnumerator ValidateShutdown() + public IEnumerator ValidateShutdown([Values] ShutdownChecks shutdownCheck) { - // Register for the server stopped notification so we know we have shutdown completely - m_ServerNetworkManager.OnServerStopped += M_ServerNetworkManager_OnServerStopped; - // Shutdown - m_ServerNetworkManager.Shutdown(); + + + if (shutdownCheck == ShutdownChecks.Server) + { + // Register for the server stopped notification so we know we have shutdown completely + m_ServerNetworkManager.OnServerStopped += OnServerStopped; + // Shutdown + m_ServerNetworkManager.Shutdown(); + } + else + { + // For this test (simplify the complexity) with a late joining client, just remove the + // in-scene placed NetworkObject prior to the client connecting + // (We are testing the shutdown sequence) + var spawnedObjects = m_ServerNetworkManager.SpawnManager.SpawnedObjectsList.ToList(); + + for (int i = spawnedObjects.Count - 1; i >= 0; i--) + { + var spawnedObject = spawnedObjects[i]; + if (spawnedObject.IsSceneObject != null && spawnedObject.IsSceneObject.Value) + { + spawnedObject.Despawn(); + } + } + + yield return s_DefaultWaitForTick; + + yield return CreateAndStartNewClient(); + + // Register for the server stopped notification so we know we have shutdown completely + m_ClientNetworkManagers[0].OnClientStopped += OnClientStopped; + m_ClientNetworkManagers[0].Shutdown(); + } + + // Let the network manager instance shutdown yield return s_DefaultWaitForTick; + + // Validate the shutdown is no longer in progress + if (shutdownCheck == ShutdownChecks.Server) + { + Assert.False(m_ServerNetworkManager.ShutdownInProgress, $"[{shutdownCheck}] Shutdown in progress was still detected!"); + } + else + { + Assert.False(m_ClientNetworkManagers[0].ShutdownInProgress, $"[{shutdownCheck}] Shutdown in progress was still detected!"); + } + } + + private void OnClientStopped(bool obj) + { + m_ServerNetworkManager.OnServerStopped -= OnClientStopped; + // Verify that we can invoke shutdown again without an exception + m_ServerNetworkManager.Shutdown(); } - private void M_ServerNetworkManager_OnServerStopped(bool obj) + private void OnServerStopped(bool obj) { - m_ServerNetworkManager.OnServerStopped -= M_ServerNetworkManager_OnServerStopped; + m_ServerNetworkManager.OnServerStopped -= OnServerStopped; // Verify that we can invoke shutdown again without an exception m_ServerNetworkManager.Shutdown(); }