fix: prevent exception when showing despawned or destroyed NetworkObject (#3029)
* fix Adding protections against exceptions in the NetworkSpawnManager.HandleNetworkObjectShow method. * test validate the fix * update adding changelog entry. * update adding PR number to changelog entry. * fix and style Removing whitespace Adding 2022.3 define for find objects.
This commit is contained in:
Родитель
ca23b3c67f
Коммит
a597b9f7ca
|
@ -13,10 +13,12 @@ Additional documentation and release notes are available at [Multiplayer Documen
|
|||
### Fixed
|
||||
|
||||
- Fixed issue where collections v2.2.x was not supported when using UTP v2.2.x within Unity v2022.3. (#3033)
|
||||
- Fixed issue where the `NetworkSpawnManager.HandleNetworkObjectShow` could throw an exception if one of the `NetworkObject` components to show was destroyed during the same frame. (#3029)
|
||||
- Fixed issue where the `NetworkManagerHelper` was continuing to check for hierarchy changes when in play mode. (#3027)
|
||||
|
||||
### Changed
|
||||
|
||||
|
||||
## [1.11.0] - 2024-08-20
|
||||
|
||||
### Added
|
||||
|
|
|
@ -1152,7 +1152,24 @@ namespace Unity.Netcode
|
|||
ulong clientId = client.Key;
|
||||
foreach (var networkObject in client.Value)
|
||||
{
|
||||
SendSpawnCallForObject(clientId, networkObject);
|
||||
// Ignore if null or not spawned (v1.x.x the server should only show what is spawned)
|
||||
if (networkObject != null && networkObject.IsSpawned)
|
||||
{
|
||||
// Prevent exceptions from interrupting this iteration
|
||||
// so the ObjectsToShowToClient list will be fully processed
|
||||
// and cleard.
|
||||
try
|
||||
{
|
||||
SendSpawnCallForObject(clientId, networkObject);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (NetworkManager.LogLevel <= LogLevel.Developer)
|
||||
{
|
||||
Debug.LogException(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ObjectsToShowToClient.Clear();
|
||||
|
|
|
@ -20,6 +20,8 @@ namespace Unity.Netcode.RuntimeTests
|
|||
private GameObject m_TestNetworkPrefab;
|
||||
private bool m_SceneManagementEnabled;
|
||||
|
||||
private GameObject m_SpawnedObject;
|
||||
|
||||
public NetworkVisibilityTests(SceneManagementState sceneManagementState)
|
||||
{
|
||||
m_SceneManagementEnabled = sceneManagementState == SceneManagementState.SceneManagementEnabled;
|
||||
|
@ -40,7 +42,7 @@ namespace Unity.Netcode.RuntimeTests
|
|||
|
||||
protected override IEnumerator OnServerAndClientsConnected()
|
||||
{
|
||||
SpawnObject(m_TestNetworkPrefab, m_ServerNetworkManager);
|
||||
m_SpawnedObject = SpawnObject(m_TestNetworkPrefab, m_ServerNetworkManager);
|
||||
|
||||
yield return base.OnServerAndClientsConnected();
|
||||
}
|
||||
|
@ -54,7 +56,43 @@ namespace Unity.Netcode.RuntimeTests
|
|||
yield return WaitForConditionOrTimeOut(() => Object.FindObjectsOfType<NetworkVisibilityComponent>().Where((c) => c.IsSpawned).Count() == 2);
|
||||
#endif
|
||||
|
||||
Assert.IsFalse(s_GlobalTimeoutHelper.TimedOut, "Timed out waiting for the visible object count to equal 2!");
|
||||
AssertOnTimeout("Timed out waiting for the visible object count to equal 2!");
|
||||
}
|
||||
|
||||
|
||||
[UnityTest]
|
||||
public IEnumerator HideShowAndDeleteTest()
|
||||
{
|
||||
#if UNITY_2023_1_OR_NEWER
|
||||
yield return WaitForConditionOrTimeOut(() => Object.FindObjectsByType<NetworkVisibilityComponent>(FindObjectsSortMode.None).Where((c) => c.IsSpawned).Count() == 2);
|
||||
#else
|
||||
yield return WaitForConditionOrTimeOut(() => Object.FindObjectsOfType<NetworkVisibilityComponent>().Where((c) => c.IsSpawned).Count() == 2);
|
||||
#endif
|
||||
AssertOnTimeout("Timed out waiting for the visible object count to equal 2!");
|
||||
|
||||
var serverNetworkObject = m_SpawnedObject.GetComponent<NetworkObject>();
|
||||
|
||||
serverNetworkObject.NetworkHide(m_ClientNetworkManagers[0].LocalClientId);
|
||||
|
||||
#if UNITY_2023_1_OR_NEWER
|
||||
yield return WaitForConditionOrTimeOut(() => Object.FindObjectsByType<NetworkVisibilityComponent>(FindObjectsSortMode.None).Where((c) => c.IsSpawned).Count() == 1);
|
||||
#else
|
||||
yield return WaitForConditionOrTimeOut(() => Object.FindObjectsOfType<NetworkVisibilityComponent>().Where((c) => c.IsSpawned).Count() == 1);
|
||||
#endif
|
||||
AssertOnTimeout($"Timed out waiting for {m_SpawnedObject.name} to be hidden from client!");
|
||||
var networkObjectId = serverNetworkObject.NetworkObjectId;
|
||||
serverNetworkObject.NetworkShow(m_ClientNetworkManagers[0].LocalClientId);
|
||||
serverNetworkObject.Despawn(true);
|
||||
|
||||
// Expect no exceptions
|
||||
yield return s_DefaultWaitForTick;
|
||||
|
||||
// Now force a scenario where it normally would have caused an exception
|
||||
m_ServerNetworkManager.SpawnManager.ObjectsToShowToClient.Add(m_ClientNetworkManagers[0].LocalClientId, new System.Collections.Generic.List<NetworkObject>());
|
||||
m_ServerNetworkManager.SpawnManager.ObjectsToShowToClient[m_ClientNetworkManagers[0].LocalClientId].Add(null);
|
||||
|
||||
// Expect no exceptions
|
||||
yield return s_DefaultWaitForTick;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче