Skip to content

fix: In-scene placed NetworkObjects getting destroyed if early disconnect #2923

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 3 additions & 10 deletions com.unity.netcode.gameobjects/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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!");
}

}
}
Loading