diff --git a/com.unity.netcode.gameobjects/CHANGELOG.md b/com.unity.netcode.gameobjects/CHANGELOG.md index e71af9c65c..b65b9f8ad2 100644 --- a/com.unity.netcode.gameobjects/CHANGELOG.md +++ b/com.unity.netcode.gameobjects/CHANGELOG.md @@ -9,25 +9,18 @@ Additional documentation and release notes are available at [Multiplayer Documen ### Added -### Fixed - -- Fixed issue where an in-scene placed `NetworkObject` with `NetworkTransform` that is also parented under a `GameObject` would not properly synchronize when the parent `GameObject` had a world space position other than 0,0,0. (#2895) - -### Changed - -## [Unreleased] - -### Added - - Added `NetworkBehaviour.OnNetworkPreSpawn` and `NetworkBehaviour.OnNetworkPostSpawn` methods that provide the ability to handle pre and post spawning actions during the `NetworkObject` spawn sequence. (#2906) - Added a client-side only `NetworkBehaviour.OnNetworkSessionSynchronized` convenience method that is invoked on all `NetworkBehaviour`s after a newly joined client has finished synchronizing with the network session in progress. (#2906) - Added `NetworkBehaviour.OnInSceneObjectsSpawned` convenience method that is invoked when all in-scene `NetworkObject`s have been spawned after a scene has been loaded or upon a host or server starting. (#2906) ### Fixed +- Fixed issue where in-scene placed NetworkObjects could be destroyed if a client disconnects early and/or before approval. (#2923) - Fixed issue where `NetworkDeltaPosition` would "jitter" periodically if both unreliable delta state updates and half-floats were used together. (#2922) - Fixed issue where `NetworkRigidbody2D` would not properly change body type based on the instance's authority when spawned. (#2916) - Fixed issue where a `NetworkObject` component's associated `NetworkBehaviour` components would not be detected if scene loading is disabled in the editor and the currently loaded scene has in-scene placed `NetworkObject`s. (#2906) +- Fixed issue where an in-scene placed `NetworkObject` with `NetworkTransform` that is also parented under a `GameObject` would not properly synchronize when the parent `GameObject` had a world space position other than 0,0,0. (#2895) + ### Changed diff --git a/com.unity.netcode.gameobjects/Runtime/Spawning/NetworkSpawnManager.cs b/com.unity.netcode.gameobjects/Runtime/Spawning/NetworkSpawnManager.cs index 794f08d21b..7852166d32 100644 --- a/com.unity.netcode.gameobjects/Runtime/Spawning/NetworkSpawnManager.cs +++ b/com.unity.netcode.gameobjects/Runtime/Spawning/NetworkSpawnManager.cs @@ -885,7 +885,7 @@ internal void DespawnAndDestroyNetworkObjects() { // If it is an in-scene placed NetworkObject then just despawn and let it be destroyed when the scene // is unloaded. Otherwise, despawn and destroy it. - var shouldDestroy = !(networkObjects[i].IsSceneObject != null && networkObjects[i].IsSceneObject.Value); + var shouldDestroy = !(networkObjects[i].IsSceneObject == null || (networkObjects[i].IsSceneObject != null && networkObjects[i].IsSceneObject.Value)); // If we are going to destroy this NetworkObject, check for any in-scene placed children that need to be removed if (shouldDestroy) diff --git a/testproject/Assets/Tests/Runtime/NetworkSceneManager/InScenePlacedNetworkObjectTests.cs b/testproject/Assets/Tests/Runtime/NetworkSceneManager/InScenePlacedNetworkObjectTests.cs index 09a8d1bf7c..8dd4d69cf8 100644 --- a/testproject/Assets/Tests/Runtime/NetworkSceneManager/InScenePlacedNetworkObjectTests.cs +++ b/testproject/Assets/Tests/Runtime/NetworkSceneManager/InScenePlacedNetworkObjectTests.cs @@ -574,4 +574,52 @@ protected bool ScaleValuesMatch(Transform transformA, Transform transformB) } } + + internal class InScenePlacedNetworkObjectClientTests : NetcodeIntegrationTest + { + private const string k_SceneToLoad = "InSceneNetworkObject"; + + protected override int NumberOfClients => 0; + + private Scene m_Scene; + + protected override IEnumerator OnSetup() + { + SceneManager.sceneLoaded += SceneManager_sceneLoaded; + SceneManager.LoadScene(k_SceneToLoad, LoadSceneMode.Additive); + return base.OnSetup(); + } + + private void SceneManager_sceneLoaded(Scene scene, LoadSceneMode loadSceneMode) + { + if (scene.name == k_SceneToLoad && loadSceneMode == LoadSceneMode.Additive) + { + m_Scene = scene; + SceneManager.sceneLoaded -= SceneManager_sceneLoaded; + } + } + + protected override IEnumerator OnTearDown() + { + if (m_Scene.isLoaded) + { + SceneManager.UnloadSceneAsync(m_Scene); + } + return base.OnTearDown(); + } + + [UnityTest] + public IEnumerator DespawnAndDestroyNetworkObjects() + { + // Simulate a client disconnecting early by just invoking DespawnAndDestroyNetworkObjects to assure + // this method does not destroy in-scene placed NetworkObjects. + m_ServerNetworkManager.SpawnManager.DespawnAndDestroyNetworkObjects(); + + yield return s_DefaultWaitForTick; + + var insceneObject = GameObject.Find("InSceneObject"); + Assert.IsNotNull(insceneObject, $"Could not find the in-scene placed {nameof(NetworkObject)}: InSceneObject!"); + } + + } }