Skip to content

Commit 0558d67

Browse files
chore: remove unwanted network object exceptions (#3867)
* Replace exceptions by logging and return. * Update log levels and types. * NotListeningException marked obsolete . * Fix `NetworkObjectParentingTests` test: - use Expect LogType.Error instead of LogType.Exception. * Keep `OverflowExceptions`: - when serialize is out of buffer space. - for deserialization buffer issue. * Styling and cleanup + replaced SceneObject by NetworkObject in log. * Add `DuplicateHideShowTest`. * Fix: `NetworkShow` behavior when it is called twice. * Changelog update.
1 parent b5b99f8 commit 0558d67

File tree

5 files changed

+115
-32
lines changed

5 files changed

+115
-32
lines changed

com.unity.netcode.gameobjects/CHANGELOG.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,18 +20,19 @@ Additional documentation and release notes are available at [Multiplayer Documen
2020

2121

2222
### Removed
23-
23+
- Removed un-needed exceptions on `NetworkObject.cs`. (#3867)
2424

2525
### Fixed
2626

2727
- Fixed issue where an attachable could log an error upon being de-spawned during shutdown. (#3895)
2828
- NestedNetworkVariables initialized with no value no longer throw an error. (#3891)
29+
- Fixed `NetworkShow` behavior when it is called twice. (#3867)
2930

3031
### Security
3132

3233

3334
### Obsolete
34-
35+
- `NotListeningException` is now marked as obsolete as it is no longer used internally. (#3867)
3536

3637
## [2.10.0] - 2026-03-01
3738

com.unity.netcode.gameobjects/Runtime/Core/NetworkObject.cs

Lines changed: 83 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1458,7 +1458,10 @@ internal NetworkSceneHandle GetSceneOriginHandle()
14581458
{
14591459
if (SceneOriginHandle.IsEmpty() && IsSpawned && IsSceneObject != false)
14601460
{
1461-
throw new Exception($"{nameof(GetSceneOriginHandle)} called when {nameof(SceneOriginHandle)} is still zero but the {nameof(NetworkObject)} is already spawned!");
1461+
if (NetworkManager.LogLevel <= LogLevel.Error)
1462+
{
1463+
NetworkLog.LogErrorServer($"{nameof(GetSceneOriginHandle)} called when {nameof(SceneOriginHandle)} is still zero but the {nameof(NetworkObject)} is already spawned!");
1464+
}
14621465
}
14631466
return !SceneOriginHandle.IsEmpty() ? SceneOriginHandle : gameObject.scene.handle;
14641467
}
@@ -1481,32 +1484,40 @@ public void NetworkShow(ulong clientId)
14811484
{
14821485
if (!IsSpawned)
14831486
{
1484-
throw new SpawnStateException("Object is not spawned");
1487+
if (NetworkManagerOwner.LogLevel <= LogLevel.Error)
1488+
{
1489+
NetworkLog.LogErrorServer($"[{name}] Attempted NetworkShow while {nameof(NetworkObject)} not spawned.");
1490+
}
1491+
return;
14851492
}
14861493

14871494
if (!HasAuthority)
14881495
{
14891496
if (NetworkManagerOwner.DistributedAuthorityMode)
14901497
{
1491-
throw new NotServerException($"Only the owner-authority can change visibility when distributed authority mode is enabled!");
1498+
if (NetworkManagerOwner.LogLevel <= LogLevel.Error)
1499+
{
1500+
NetworkLog.LogError($"[{name}] Only the owner-authority can change visibility when distributed authority mode is enabled!");
1501+
}
1502+
return;
14921503
}
14931504
else
14941505
{
1495-
throw new NotServerException("Only the authority can change visibility");
1506+
if (NetworkManagerOwner.LogLevel <= LogLevel.Error)
1507+
{
1508+
NetworkLog.LogError($"[{name}] Only the server can change visibility!");
1509+
}
1510+
return;
14961511
}
14971512
}
14981513

14991514
if (Observers.Contains(clientId))
15001515
{
1501-
if (NetworkManagerOwner.DistributedAuthorityMode)
1502-
{
1503-
Debug.LogError($"The object {name} is already visible to Client-{clientId}!");
1504-
return;
1505-
}
1506-
else
1516+
if (NetworkManagerOwner.LogLevel <= LogLevel.Developer)
15071517
{
1508-
throw new NotServerException("Only server can change visibility");
1518+
NetworkLog.LogWarning($"[{name}] {nameof(NetworkObject)} is already visible to Client-{clientId}! (ignoring)");
15091519
}
1520+
return;
15101521
}
15111522

15121523
if (CheckObjectVisibility != null && !CheckObjectVisibility(clientId))
@@ -1556,8 +1567,8 @@ public static void NetworkShow(List<NetworkObject> networkObjects, ulong clientI
15561567
/// <remarks>
15571568
/// Usage: Use to stop sending updates to the targeted client, "netcode invisible", for a currently visible <see cref="NetworkObject"/>.<br />
15581569
/// <br />
1559-
/// Dynamically Spawned: <see cref="NetworkObject"/>s will be despawned and destroyed on the targeted client's side.<br />
1560-
/// In-Scene Placed: <see cref="NetworkObject"/>s will only be despawned on the targeted client's side.<br />
1570+
/// Dynamically Spawned: <see cref="NetworkObject"/>s will be de-spawned and destroyed on the targeted client's side.<br />
1571+
/// In-Scene Placed: <see cref="NetworkObject"/>s will only be de-spawned on the targeted client's side.<br />
15611572
/// <br />
15621573
/// See Also:<br />
15631574
/// <see cref="NetworkHide(List{NetworkObject}, ulong)"/><br />
@@ -1568,18 +1579,30 @@ public void NetworkHide(ulong clientId)
15681579
{
15691580
if (!IsSpawned)
15701581
{
1571-
throw new SpawnStateException("Object is not spawned");
1582+
if (NetworkManager.LogLevel <= LogLevel.Error)
1583+
{
1584+
NetworkLog.LogErrorServer($"[{name}] Attempted NetworkHide while {nameof(NetworkObject)} is not spawned.");
1585+
}
1586+
return;
15721587
}
15731588

1574-
if (!HasAuthority && !NetworkManagerOwner.DAHost)
1589+
if (!HasAuthority)
15751590
{
15761591
if (NetworkManagerOwner.DistributedAuthorityMode)
15771592
{
1578-
throw new NotServerException($"Only the owner-authority can change visibility when distributed authority mode is enabled!");
1593+
if (NetworkManagerOwner.LogLevel <= LogLevel.Error)
1594+
{
1595+
NetworkLog.LogError($"[{name}] Only the owner-authority can change visibility when distributed authority mode is enabled!");
1596+
}
1597+
return;
15791598
}
15801599
else
15811600
{
1582-
throw new NotServerException("Only the authority can change visibility");
1601+
if (NetworkManagerOwner.LogLevel <= LogLevel.Error)
1602+
{
1603+
NetworkLog.LogError($"[{name}] Only the server can change visibility!");
1604+
}
1605+
return;
15831606
}
15841607
}
15851608

@@ -1589,9 +1612,9 @@ public void NetworkHide(ulong clientId)
15891612
{
15901613
if (NetworkManagerOwner.LogLevel <= LogLevel.Developer)
15911614
{
1592-
Debug.LogWarning($"{name} is already hidden from Client-{clientId}! (ignoring)");
1593-
return;
1615+
NetworkLog.LogWarning($"[{name}] {nameof(NetworkObject)} already hidden from Client-{clientId}! (ignoring)");
15941616
}
1617+
return;
15951618
}
15961619
Observers.Remove(clientId);
15971620

@@ -1724,18 +1747,30 @@ internal void SpawnInternal(bool destroyWithScene, ulong ownerClientId, bool pla
17241747

17251748
if (!NetworkManagerOwner.IsListening)
17261749
{
1727-
throw new NotListeningException($"{nameof(NetworkManagerOwner)} is not listening, start a server or host before spawning objects");
1750+
if (NetworkManagerOwner.LogLevel <= LogLevel.Error)
1751+
{
1752+
NetworkLog.LogError($"[{name}] {nameof(NetworkManagerOwner)} is not listening, start a server or host before spawning objects.");
1753+
}
1754+
return;
17281755
}
17291756

17301757
if ((!NetworkManagerOwner.IsServer && !NetworkManagerOwner.DistributedAuthorityMode) || (NetworkManagerOwner.DistributedAuthorityMode && !NetworkManagerOwner.LocalClient.IsSessionOwner && NetworkManagerOwner.LocalClientId != ownerClientId))
17311758
{
17321759
if (NetworkManagerOwner.DistributedAuthorityMode)
17331760
{
1734-
throw new NotServerException($"When distributed authority mode is enabled, you can only spawn NetworkObjects that belong to the local instance! Local instance id {NetworkManagerOwner.LocalClientId} is not the same as the assigned owner id: {ownerClientId}!");
1761+
if (NetworkManagerOwner.LogLevel <= LogLevel.Error)
1762+
{
1763+
NetworkLog.LogError($"[{name}] When distributed authority mode is enabled, you can only spawn NetworkObjects that belong to the local instance! Local instance id {NetworkManagerOwner.LocalClientId} is not the same as the assigned owner id: {ownerClientId}!");
1764+
}
1765+
return;
17351766
}
17361767
else
17371768
{
1738-
throw new NotServerException($"Only server can spawn {nameof(NetworkObject)}s");
1769+
if (NetworkManagerOwner.LogLevel <= LogLevel.Error)
1770+
{
1771+
NetworkLog.LogError($"[{name}] Only server can spawn {nameof(NetworkObject)}s.");
1772+
}
1773+
return;
17391774
}
17401775
}
17411776

@@ -2256,7 +2291,10 @@ private void OnTransformParentChanged()
22562291
return;
22572292
}
22582293
transform.parent = m_CachedParent;
2259-
Debug.LogException(new NotListeningException($"[{name}] {nameof(networkManager)} is not listening, start a server or host before re-parenting"));
2294+
if (NetworkManagerOwner.LogLevel <= LogLevel.Error)
2295+
{
2296+
NetworkLog.LogError($"[{name}] {nameof(networkManager)} is not listening, start a server or host before re-parenting.");
2297+
}
22602298
return;
22612299
}
22622300

@@ -2273,7 +2311,10 @@ private void OnTransformParentChanged()
22732311
else
22742312
{
22752313
transform.parent = m_CachedParent;
2276-
Debug.LogException(new SpawnStateException($"[{name}] {nameof(NetworkObject)} can only be re-parented after being spawned"));
2314+
if (NetworkManagerOwner.LogLevel <= LogLevel.Error)
2315+
{
2316+
NetworkLog.LogErrorServer($"[{name}] {nameof(NetworkObject)} can only be re-parented after being spawned!");
2317+
}
22772318
}
22782319
return;
22792320
}
@@ -2293,7 +2334,7 @@ private void OnTransformParentChanged()
22932334
}
22942335
else
22952336
{
2296-
Debug.LogException(new NotServerException($"[{name}] Only the server can re-parent {nameof(NetworkObject)}s"));
2337+
NetworkLog.LogError($"[{name}] Only the server can re-parent {nameof(NetworkObject)}s.");
22972338
}
22982339
}
22992340
return;
@@ -2307,14 +2348,20 @@ private void OnTransformParentChanged()
23072348
{
23082349
transform.parent = m_CachedParent;
23092350
AuthorityAppliedParenting = false;
2310-
Debug.LogException(new InvalidParentException($"[{name}] Invalid parenting, {nameof(NetworkObject)} moved under a non-{nameof(NetworkObject)} parent"));
2351+
if (NetworkManagerOwner.LogLevel <= LogLevel.Error)
2352+
{
2353+
NetworkLog.LogErrorServer($"[{name}] Invalid parenting, {nameof(NetworkObject)} moved under a non-{nameof(NetworkObject)} parent");
2354+
}
23112355
return;
23122356
}
23132357
else if (!parentObject.IsSpawned)
23142358
{
23152359
transform.parent = m_CachedParent;
23162360
AuthorityAppliedParenting = false;
2317-
Debug.LogException(new SpawnStateException($"[{name}] {nameof(NetworkObject)} can only be re-parented under another spawned {nameof(NetworkObject)}"));
2361+
if (NetworkManagerOwner.LogLevel <= LogLevel.Error)
2362+
{
2363+
NetworkLog.LogErrorServer($"[{name}] {nameof(NetworkObject)} can only be re-parented under another spawned {nameof(NetworkObject)}.");
2364+
}
23182365
return;
23192366
}
23202367

@@ -2536,7 +2583,10 @@ internal void InvokeBehaviourNetworkSpawn()
25362583
{
25372584
if (!childBehaviour.gameObject.activeInHierarchy)
25382585
{
2539-
Debug.LogWarning($"{GenerateDisabledNetworkBehaviourWarning(childBehaviour)}");
2586+
if (NetworkManagerOwner.LogLevel <= LogLevel.Developer)
2587+
{
2588+
NetworkLog.LogWarning($"{GenerateDisabledNetworkBehaviourWarning(childBehaviour)}");
2589+
}
25402590
continue;
25412591
}
25422592
childBehaviour.InternalOnNetworkSpawn();
@@ -3327,7 +3377,11 @@ internal static NetworkObject Deserialize(in SerializedObject serializedObject,
33273377
// Spawn the NetworkObject
33283378
if (networkObject.IsSpawned)
33293379
{
3330-
throw new SpawnStateException($"[{networkObject.name}] Object-{networkObject.NetworkObjectId} is already spawned!");
3380+
if (NetworkManager.Singleton.LogLevel <= LogLevel.Error)
3381+
{
3382+
NetworkLog.LogErrorServer($"[{networkObject.name}] Object-{networkObject.NetworkObjectId} is already spawned!");
3383+
}
3384+
return null;
33313385
}
33323386

33333387
// Invoke the non-authority local spawn method

com.unity.netcode.gameobjects/Runtime/Exceptions/NotListeningException.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ namespace Unity.Netcode
55
/// <summary>
66
/// Exception thrown when the operation require NetworkManager to be listening.
77
/// </summary>
8+
[Obsolete("Not used anymore.")]
89
public class NotListeningException : Exception
910
{
1011
/// <summary>

com.unity.netcode.gameobjects/Tests/Runtime/NetworkShowHideTests.cs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -892,5 +892,32 @@ public IEnumerator NetworkShowAndChangeOwnership()
892892
AssertOnTimeout($"Timed out waiting for clients-{m_NewOwner.LocalClientId} to gain ownership of object {m_OwnershipNetworkObject.NetworkObjectId}!");
893893
VerboseDebug($"Client {m_NewOwner.LocalClientId} now owns object {m_OwnershipNetworkObject.NetworkObjectId}!");
894894
}
895+
896+
[UnityTest]
897+
public IEnumerator DuplicateHideShowTest()
898+
{
899+
var authority = GetAuthorityNetworkManager();
900+
var nonAuthority = GetNonAuthorityNetworkManager();
901+
m_ClientId0 = nonAuthority.LocalClientId;
902+
ShowHideObject.ClientTargetedNetworkObjects.Clear();
903+
ShowHideObject.ClientIdToTarget = m_ClientId0;
904+
ShowHideObject.Silent = true;
905+
906+
var spawnedObject1 = SpawnObject(m_PrefabToSpawn, authority);
907+
m_NetSpawnedObject1 = spawnedObject1.GetComponent<NetworkObject>();
908+
909+
m_NetSpawnedObject1.GetComponent<ShowHideObject>().MyNetworkVariable.Value++;
910+
m_NetSpawnedObject1.NetworkHide(m_ClientId0);
911+
m_NetSpawnedObject1.NetworkHide(m_ClientId0);
912+
913+
yield return WaitForConditionOrTimeOut(() => !nonAuthority.SpawnManager.SpawnedObjects.ContainsKey(m_NetSpawnedObject1.NetworkObjectId));
914+
AssertOnTimeout($"NetworkObject {m_NetSpawnedObject1.name} is still spawned on client-{nonAuthority.LocalClientId} after timeout!");
915+
916+
m_NetSpawnedObject1.NetworkShow(m_ClientId0);
917+
m_NetSpawnedObject1.NetworkShow(m_ClientId0);
918+
919+
yield return WaitForConditionOrTimeOut(() => nonAuthority.SpawnManager.SpawnedObjects.ContainsKey(m_NetSpawnedObject1.NetworkObjectId));
920+
AssertOnTimeout($"NetworkObject {m_NetSpawnedObject1.name} is not yet spawned on client-{nonAuthority.LocalClientId} after timeout!");
921+
}
895922
}
896923
}

testproject/Assets/Tests/Runtime/ObjectParenting/NetworkObjectParentingTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ public void SetupSet(Transform rootTransform, int setIndex, NetworkManager netwo
207207
Assert.That(m_Pickup_NetObjs[setIndex], Is.Not.Null);
208208
Assert.That(m_Pickup_Back_NetObjs[setIndex], Is.Not.Null);
209209

210-
LogAssert.Expect(LogType.Exception, new Regex("start a server or host", RegexOptions.IgnoreCase));
210+
LogAssert.Expect(LogType.Error, new Regex("start a server or host", RegexOptions.IgnoreCase));
211211
var cachedParent = m_Cube_NetObjs[setIndex].parent;
212212
m_Cube_NetObjs[setIndex].parent = m_Pickup_NetObjs[setIndex];
213213
Assert.That(m_Cube_NetObjs[setIndex].parent, Is.EqualTo(cachedParent), $"Transform {m_Cube_NetObjs[setIndex].parent.name} is not equal to transform {cachedParent.name}");

0 commit comments

Comments
 (0)