From cda4b95272214768ab19336fd7f3228e99b3154d Mon Sep 17 00:00:00 2001 From: Larus Olafsson Date: Thu, 23 Oct 2025 15:07:05 +0000 Subject: [PATCH 1/9] fix: add better error messages for a couple of error cases - When using a generic INetworkSerializable+IEquatable combo and update documentation with workaround - When there are no initialized elements in the network prefab list (fix null reference exception) --- .../Documentation~/basics/networkvariable.md | 52 +++++++++++++++++++ .../Editor/CodeGen/NetworkBehaviourILPP.cs | 9 +++- .../Editor/NetworkManagerEditor.cs | 5 ++ .../Runtime/Configuration/NetworkPrefabs.cs | 12 +++++ .../NetworkManagerConfigurationTests.cs | 30 +++++++++++ 5 files changed, 107 insertions(+), 1 deletion(-) diff --git a/com.unity.netcode.gameobjects/Documentation~/basics/networkvariable.md b/com.unity.netcode.gameobjects/Documentation~/basics/networkvariable.md index ab648a7056..c5f1dc69d7 100644 --- a/com.unity.netcode.gameobjects/Documentation~/basics/networkvariable.md +++ b/com.unity.netcode.gameobjects/Documentation~/basics/networkvariable.md @@ -621,3 +621,55 @@ public class TestFixedString : NetworkBehaviour > [!NOTE] > The above example uses a pre-set list of strings to cycle through for example purposes only. If you have a predefined set of text strings as part of your actual design then you would not want to use a FixedString to handle synchronizing the changes to `m_TextString`. Instead, you would want to use a `uint` for the type `T` where the `uint` was the index of the string message to apply to `m_TextString`. + +## Generic IEquatable network variables + +Generic `INetworkSerializable` types with generic `IEquatable` are not supported, implemented as `public class NotSupported : INetworkSerializable, IEquatable>` where the type would be passed in during declaration like `NetworkVariable> myVar;`. + +The recommended workaround for this would be to create the generic class as usual but add a virtual method for handling the serialization of the type. Then wrap this generic `INetworkSerializable` in a derived class which then needs to have a serializable type defined where the implementation for the serialization is provided. + +For example: + +```csharp +public class FirstGenClass : INetworkSerializable +{ + // This needs to be a serializable type according to what network variables support + public T Data; + + protected virtual void OnNetworkSerialize(BufferSerializer serializer) where T2 : IReaderWriter + { + } + + public void NetworkSerialize(BufferSerializer serializer) where T2 : IReaderWriter + { + OnNetworkSerialize(serializer); + } +} + +public class SecondGenWithLong : FirstGenClass, IEquatable +{ + // Potential additional data + public int AdditionalData; + + protected virtual bool OnEquals(SecondGenWithLong other) + { + return other.Data.Equals(other); + } + public bool Equals(SecondGenWithLong other) + { + return OnEquals(other); + } + + protected override void OnNetworkSerialize(BufferSerializer serializer) + { + serializer.SerializeValue(ref AdditionalData); + serializer.SerializeValue(ref Data); + } +} +``` + +Then declare this network variable like so: + +```csharp +NetworkVariable myVar = new NetworkVariable(); +``` \ No newline at end of file diff --git a/com.unity.netcode.gameobjects/Editor/CodeGen/NetworkBehaviourILPP.cs b/com.unity.netcode.gameobjects/Editor/CodeGen/NetworkBehaviourILPP.cs index 5396087381..7688b16c62 100644 --- a/com.unity.netcode.gameobjects/Editor/CodeGen/NetworkBehaviourILPP.cs +++ b/com.unity.netcode.gameobjects/Editor/CodeGen/NetworkBehaviourILPP.cs @@ -409,7 +409,14 @@ private void CreateNetworkVariableTypeInitializers(AssemblyDefinition assembly, } else { - m_Diagnostics.AddError($"{type}: Managed type in NetworkVariable must implement IEquatable<{type}>"); + foreach (var typeInterface in type.Resolve().Interfaces) + { + if (typeInterface.InterfaceType.Name.Contains(typeof(IEquatable<>).Name) && typeInterface.InterfaceType.IsGenericInstance) + { + m_Diagnostics.AddError($"{type}: A generic IEquatable '{typeInterface.InterfaceType.FullName}' is not supported."); + } + } + m_Diagnostics.AddError($"{type}: Managed type in NetworkVariable must implement IEquatable<{type}>."); equalityMethod = new GenericInstanceMethod(m_NetworkVariableSerializationTypes_InitializeEqualityChecker_ManagedClassEquals_MethodRef); } diff --git a/com.unity.netcode.gameobjects/Editor/NetworkManagerEditor.cs b/com.unity.netcode.gameobjects/Editor/NetworkManagerEditor.cs index 69e5de3ee0..b5f0879118 100644 --- a/com.unity.netcode.gameobjects/Editor/NetworkManagerEditor.cs +++ b/com.unity.netcode.gameobjects/Editor/NetworkManagerEditor.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.IO; +using System.Linq; using Unity.Netcode.Editor.Configuration; using UnityEditor; using UnityEngine; @@ -301,6 +302,10 @@ private void DisplayNetworkManagerProperties() { EditorGUILayout.HelpBox("You have no prefab list selected. You will have to add your prefabs manually at runtime for netcode to work.", MessageType.Warning); } + else if (m_NetworkManager.NetworkConfig.Prefabs.NetworkPrefabsLists.All(x => x == null)) + { + EditorGUILayout.HelpBox("All prefab lists selected are uninitialized. You will have to add your prefabs manually at runtime for netcode to work.", MessageType.Warning); + } EditorGUILayout.PropertyField(m_PrefabsList); } diff --git a/com.unity.netcode.gameobjects/Runtime/Configuration/NetworkPrefabs.cs b/com.unity.netcode.gameobjects/Runtime/Configuration/NetworkPrefabs.cs index 77b30700b7..ceecb875a9 100644 --- a/com.unity.netcode.gameobjects/Runtime/Configuration/NetworkPrefabs.cs +++ b/com.unity.netcode.gameobjects/Runtime/Configuration/NetworkPrefabs.cs @@ -81,6 +81,10 @@ internal void Shutdown() { foreach (var list in NetworkPrefabsLists) { + if (list == null) + { + continue; + } list.OnAdd -= AddTriggeredByNetworkPrefabList; list.OnRemove -= RemoveTriggeredByNetworkPrefabList; } @@ -96,6 +100,10 @@ public void Initialize(bool warnInvalid = true) m_Prefabs.Clear(); foreach (var list in NetworkPrefabsLists) { + if (list == null) + { + continue; + } list.OnAdd += AddTriggeredByNetworkPrefabList; list.OnRemove += RemoveTriggeredByNetworkPrefabList; } @@ -109,6 +117,10 @@ public void Initialize(bool warnInvalid = true) { foreach (var list in NetworkPrefabsLists) { + if (list == null) + { + continue; + } prefabs.AddRange(list.PrefabList); } } diff --git a/com.unity.netcode.gameobjects/Tests/Editor/NetworkManagerConfigurationTests.cs b/com.unity.netcode.gameobjects/Tests/Editor/NetworkManagerConfigurationTests.cs index 78b13e3abc..67356858af 100644 --- a/com.unity.netcode.gameobjects/Tests/Editor/NetworkManagerConfigurationTests.cs +++ b/com.unity.netcode.gameobjects/Tests/Editor/NetworkManagerConfigurationTests.cs @@ -294,6 +294,36 @@ public void WhenModifyingPrefabListUsingPrefabsAPI_ModificationIsLocal() } } + [Test] + public void WhenThereAreUninitializedElementsInPrefabsList_NoErrors() + { + // Setup + var networkManagerObject = new GameObject(); + var networkManager = networkManagerObject.AddComponent(); + networkManager.NetworkConfig = new NetworkConfig + { + NetworkTransport = networkManager.gameObject.AddComponent() + }; + + try + { + networkManager.NetworkConfig.Prefabs.NetworkPrefabsLists = new List { null }; + networkManager.Initialize(true); + + Assert.IsTrue(networkManager.NetworkConfig.Prefabs.NetworkPrefabsLists.Count == 1); + Assert.IsTrue(networkManager.NetworkConfig.Prefabs.NetworkPrefabsLists[0] == null); + Assert.IsTrue(networkManager.NetworkConfig.Prefabs.Prefabs.Count == 0); + } + finally + { + networkManager.ShutdownInternal(); + // Shutdown doesn't get called correctly because we called Initialize() + // instead of calling StartHost/StartClient/StartServer. See MTT-860 for + // why. + networkManager.NetworkConfig?.NetworkTransport.Shutdown(); + } + } + [Test] public void WhenModifyingPrefabListUsingPrefabsListAPI_ModificationIsShared() { From dc42deb8f18428f8e9f7ae9bbdc257909cfac745 Mon Sep 17 00:00:00 2001 From: Larus Olafsson Date: Thu, 23 Oct 2025 15:28:47 +0000 Subject: [PATCH 2/9] update changelog --- com.unity.netcode.gameobjects/CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/com.unity.netcode.gameobjects/CHANGELOG.md b/com.unity.netcode.gameobjects/CHANGELOG.md index ab7434e0fa..5afacc140c 100644 --- a/com.unity.netcode.gameobjects/CHANGELOG.md +++ b/com.unity.netcode.gameobjects/CHANGELOG.md @@ -21,6 +21,7 @@ Additional documentation and release notes are available at [Multiplayer Documen - Changed the default `NetworkDelivery` used by all messages is now reliable fragmented sequenced with the exception of named, unnamed, and any messages sent with a user specified network delivery type. This assures certain order of operations to be preserved when same call-stack changes are applied to a newly spawned, authority side, NetworkObject. (#3664) - Changed NetworkTransform documentation to better reflect the Teleport methods intended usage along with updates to NetworkObject and physics areas of the documentation. (#3664) - The first session owner no longer sends two synchronization messages to the service. (#3563) +- Better error message when using generic IEquatable in a generic INetworkSerializable class and updated documentation with workaround. ### Deprecated @@ -34,6 +35,7 @@ Additional documentation and release notes are available at [Multiplayer Documen - Fixed NetworkTransform state synchronization issue when `NetworkTransform.SwitchTransformSpaceWhenParented` is enabled and the associated NetworkObject is parented multiple times in a single frame or within a couple of frames. (#3664) - Fixed issue when spawning, parenting, and immediately re-parenting when `NetworkTransform.SwitchTransformSpaceWhenParented` is enabled. (#3664) - Fixed issue where the disconnect event and provided message was too generic to know why the disconnect occurred. (#3551) +- Exception when the network prefab list in the network manager has uninitialized elements. ### Security From 3bf433044d734a9df55c6014847c6c9618bed842 Mon Sep 17 00:00:00 2001 From: Noel Stephens Date: Thu, 23 Oct 2025 10:56:28 -0500 Subject: [PATCH 3/9] style Removing single whitespace at end of sentence. --- .../Documentation~/basics/networkvariable.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/com.unity.netcode.gameobjects/Documentation~/basics/networkvariable.md b/com.unity.netcode.gameobjects/Documentation~/basics/networkvariable.md index c5f1dc69d7..4e46e5862a 100644 --- a/com.unity.netcode.gameobjects/Documentation~/basics/networkvariable.md +++ b/com.unity.netcode.gameobjects/Documentation~/basics/networkvariable.md @@ -626,7 +626,7 @@ public class TestFixedString : NetworkBehaviour Generic `INetworkSerializable` types with generic `IEquatable` are not supported, implemented as `public class NotSupported : INetworkSerializable, IEquatable>` where the type would be passed in during declaration like `NetworkVariable> myVar;`. -The recommended workaround for this would be to create the generic class as usual but add a virtual method for handling the serialization of the type. Then wrap this generic `INetworkSerializable` in a derived class which then needs to have a serializable type defined where the implementation for the serialization is provided. +The recommended workaround for this would be to create the generic class as usual but add a virtual method for handling the serialization of the type. Then wrap this generic `INetworkSerializable` in a derived class which then needs to have a serializable type defined where the implementation for the serialization is provided. For example: From db0eedb79cd57010810d325f8b9a0fbc606c28cb Mon Sep 17 00:00:00 2001 From: Noel Stephens Date: Thu, 23 Oct 2025 11:01:44 -0500 Subject: [PATCH 4/9] style Keeping the most recent changelog entry chronologically ordered (ordered by PR number). --- com.unity.netcode.gameobjects/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/com.unity.netcode.gameobjects/CHANGELOG.md b/com.unity.netcode.gameobjects/CHANGELOG.md index 649d1762b0..b249242a5f 100644 --- a/com.unity.netcode.gameobjects/CHANGELOG.md +++ b/com.unity.netcode.gameobjects/CHANGELOG.md @@ -15,6 +15,7 @@ Additional documentation and release notes are available at [Multiplayer Documen ### Changed +- Better error message when using generic IEquatable in a generic INetworkSerializable class and updated documentation with workaround. (#3739) - The `NetworkManager` functions `GetTransportIdFromClientId` and `GetClientIdFromTransportId` will now return `ulong.MaxValue` when the clientId or transportId do not exist. (#3707) - Changed NetworkShow to send a message at the end of the frame and force a NetworkVariable synchronization prior to generating the CreateObjectMessage as opposed to waiting until the next network tick to synchronize the show with the update to NetworkVariables. (#3664) - Changed NetworkTransform now synchronizes `NetworkTransform.SwitchTransformSpaceWhenParented` when it is updated by the motion model authority. (#3664) @@ -22,7 +23,6 @@ Additional documentation and release notes are available at [Multiplayer Documen - Changed the default `NetworkDelivery` used by all messages is now reliable fragmented sequenced with the exception of named, unnamed, and any messages sent with a user specified network delivery type. This assures certain order of operations to be preserved when same call-stack changes are applied to a newly spawned, authority side, NetworkObject. (#3664) - Changed NetworkTransform documentation to better reflect the Teleport methods intended usage along with updates to NetworkObject and physics areas of the documentation. (#3664) - The first session owner no longer sends two synchronization messages to the service. (#3563) -- Better error message when using generic IEquatable in a generic INetworkSerializable class and updated documentation with workaround. ### Deprecated From 5ab942033d6c409827f3379e486e997ee9d4bc55 Mon Sep 17 00:00:00 2001 From: Larus Olafsson Date: Thu, 23 Oct 2025 22:48:51 +0000 Subject: [PATCH 5/9] Apply suggestions from code review Co-authored-by: Emma --- .../Documentation~/basics/networkvariable.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/com.unity.netcode.gameobjects/Documentation~/basics/networkvariable.md b/com.unity.netcode.gameobjects/Documentation~/basics/networkvariable.md index 4e46e5862a..f6a9f376ec 100644 --- a/com.unity.netcode.gameobjects/Documentation~/basics/networkvariable.md +++ b/com.unity.netcode.gameobjects/Documentation~/basics/networkvariable.md @@ -631,7 +631,7 @@ The recommended workaround for this would be to create the generic class as usua For example: ```csharp -public class FirstGenClass : INetworkSerializable +public class MyGameData : INetworkSerializable { // This needs to be a serializable type according to what network variables support public T Data; @@ -646,16 +646,16 @@ public class FirstGenClass : INetworkSerializable } } -public class SecondGenWithLong : FirstGenClass, IEquatable +public class GameDataWithLong : MyGameData, IEquatable { // Potential additional data public int AdditionalData; - protected virtual bool OnEquals(SecondGenWithLong other) + protected virtual bool OnEquals(GameDataWithLong other) { return other.Data.Equals(other); } - public bool Equals(SecondGenWithLong other) + public bool Equals(GameDataWithLong other) { return OnEquals(other); } @@ -671,5 +671,5 @@ public class SecondGenWithLong : FirstGenClass, IEquatable myVar = new NetworkVariable(); +NetworkVariable myVar = new NetworkVariable(); ``` \ No newline at end of file From 6c43349db69104070dc7f236205a8d4e0a62191d Mon Sep 17 00:00:00 2001 From: Larus Olafsson Date: Thu, 23 Oct 2025 22:50:22 +0000 Subject: [PATCH 6/9] add missing pr number --- com.unity.netcode.gameobjects/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/com.unity.netcode.gameobjects/CHANGELOG.md b/com.unity.netcode.gameobjects/CHANGELOG.md index b249242a5f..7c5bb85e8d 100644 --- a/com.unity.netcode.gameobjects/CHANGELOG.md +++ b/com.unity.netcode.gameobjects/CHANGELOG.md @@ -37,7 +37,7 @@ Additional documentation and release notes are available at [Multiplayer Documen - Fixed NetworkTransform state synchronization issue when `NetworkTransform.SwitchTransformSpaceWhenParented` is enabled and the associated NetworkObject is parented multiple times in a single frame or within a couple of frames. (#3664) - Fixed issue when spawning, parenting, and immediately re-parenting when `NetworkTransform.SwitchTransformSpaceWhenParented` is enabled. (#3664) - Fixed issue where the disconnect event and provided message was too generic to know why the disconnect occurred. (#3551) -- Exception when the network prefab list in the network manager has uninitialized elements. +- Exception when the network prefab list in the network manager has uninitialized elements. (#3739) ### Security From 4c9cfb57bf4fe911d901585d40587e7a8ef0b2c8 Mon Sep 17 00:00:00 2001 From: Larus Olafsson Date: Thu, 23 Oct 2025 22:53:27 +0000 Subject: [PATCH 7/9] move to inetworkserializable section --- .../serialization/inetworkserializable.md | 52 +++++++++++++++++++ .../Documentation~/basics/networkvariable.md | 52 ------------------- 2 files changed, 52 insertions(+), 52 deletions(-) diff --git a/com.unity.netcode.gameobjects/Documentation~/advanced-topics/serialization/inetworkserializable.md b/com.unity.netcode.gameobjects/Documentation~/advanced-topics/serialization/inetworkserializable.md index e75f9a9c49..3f7dcd689e 100644 --- a/com.unity.netcode.gameobjects/Documentation~/advanced-topics/serialization/inetworkserializable.md +++ b/com.unity.netcode.gameobjects/Documentation~/advanced-topics/serialization/inetworkserializable.md @@ -181,3 +181,55 @@ public struct MyStructB : MyStructA } } ``` + +## Generic IEquatable network variables + +Generic `INetworkSerializable` types with generic `IEquatable` are not supported, implemented as `public class NotSupported : INetworkSerializable, IEquatable>` where the type would be passed in during declaration like `NetworkVariable> myVar;`. + +The recommended workaround for this would be to create the generic class as usual but add a virtual method for handling the serialization of the type. Then wrap this generic `INetworkSerializable` in a derived class which then needs to have a serializable type defined where the implementation for the serialization is provided. + +For example: + +```csharp +public class MyGameData : INetworkSerializable +{ + // This needs to be a serializable type according to what network variables support + public T Data; + + protected virtual void OnNetworkSerialize(BufferSerializer serializer) where T2 : IReaderWriter + { + } + + public void NetworkSerialize(BufferSerializer serializer) where T2 : IReaderWriter + { + OnNetworkSerialize(serializer); + } +} + +public class GameDataWithLong : MyGameData, IEquatable +{ + // Potential additional data + public int AdditionalData; + + protected virtual bool OnEquals(GameDataWithLong other) + { + return other.Data.Equals(other); + } + public bool Equals(GameDataWithLong other) + { + return OnEquals(other); + } + + protected override void OnNetworkSerialize(BufferSerializer serializer) + { + serializer.SerializeValue(ref AdditionalData); + serializer.SerializeValue(ref Data); + } +} +``` + +Then declare this network variable like so: + +```csharp +NetworkVariable myVar = new NetworkVariable(); +``` \ No newline at end of file diff --git a/com.unity.netcode.gameobjects/Documentation~/basics/networkvariable.md b/com.unity.netcode.gameobjects/Documentation~/basics/networkvariable.md index f6a9f376ec..ab648a7056 100644 --- a/com.unity.netcode.gameobjects/Documentation~/basics/networkvariable.md +++ b/com.unity.netcode.gameobjects/Documentation~/basics/networkvariable.md @@ -621,55 +621,3 @@ public class TestFixedString : NetworkBehaviour > [!NOTE] > The above example uses a pre-set list of strings to cycle through for example purposes only. If you have a predefined set of text strings as part of your actual design then you would not want to use a FixedString to handle synchronizing the changes to `m_TextString`. Instead, you would want to use a `uint` for the type `T` where the `uint` was the index of the string message to apply to `m_TextString`. - -## Generic IEquatable network variables - -Generic `INetworkSerializable` types with generic `IEquatable` are not supported, implemented as `public class NotSupported : INetworkSerializable, IEquatable>` where the type would be passed in during declaration like `NetworkVariable> myVar;`. - -The recommended workaround for this would be to create the generic class as usual but add a virtual method for handling the serialization of the type. Then wrap this generic `INetworkSerializable` in a derived class which then needs to have a serializable type defined where the implementation for the serialization is provided. - -For example: - -```csharp -public class MyGameData : INetworkSerializable -{ - // This needs to be a serializable type according to what network variables support - public T Data; - - protected virtual void OnNetworkSerialize(BufferSerializer serializer) where T2 : IReaderWriter - { - } - - public void NetworkSerialize(BufferSerializer serializer) where T2 : IReaderWriter - { - OnNetworkSerialize(serializer); - } -} - -public class GameDataWithLong : MyGameData, IEquatable -{ - // Potential additional data - public int AdditionalData; - - protected virtual bool OnEquals(GameDataWithLong other) - { - return other.Data.Equals(other); - } - public bool Equals(GameDataWithLong other) - { - return OnEquals(other); - } - - protected override void OnNetworkSerialize(BufferSerializer serializer) - { - serializer.SerializeValue(ref AdditionalData); - serializer.SerializeValue(ref Data); - } -} -``` - -Then declare this network variable like so: - -```csharp -NetworkVariable myVar = new NetworkVariable(); -``` \ No newline at end of file From 1425f5698410facbac89d4f0f1d0b7ddb3d52b62 Mon Sep 17 00:00:00 2001 From: Larus Olafsson Date: Thu, 23 Oct 2025 23:12:04 +0000 Subject: [PATCH 8/9] switch to testing NetworkConfig directly --- .../NetworkManagerConfigurationTests.cs | 32 ++++++------------- 1 file changed, 9 insertions(+), 23 deletions(-) diff --git a/com.unity.netcode.gameobjects/Tests/Editor/NetworkManagerConfigurationTests.cs b/com.unity.netcode.gameobjects/Tests/Editor/NetworkManagerConfigurationTests.cs index 67356858af..3dbb431d20 100644 --- a/com.unity.netcode.gameobjects/Tests/Editor/NetworkManagerConfigurationTests.cs +++ b/com.unity.netcode.gameobjects/Tests/Editor/NetworkManagerConfigurationTests.cs @@ -297,31 +297,17 @@ public void WhenModifyingPrefabListUsingPrefabsAPI_ModificationIsLocal() [Test] public void WhenThereAreUninitializedElementsInPrefabsList_NoErrors() { - // Setup - var networkManagerObject = new GameObject(); - var networkManager = networkManagerObject.AddComponent(); - networkManager.NetworkConfig = new NetworkConfig - { - NetworkTransport = networkManager.gameObject.AddComponent() - }; + var networkConfig = new NetworkConfig(); - try - { - networkManager.NetworkConfig.Prefabs.NetworkPrefabsLists = new List { null }; - networkManager.Initialize(true); + networkConfig.Prefabs.NetworkPrefabsLists = new List { null }; - Assert.IsTrue(networkManager.NetworkConfig.Prefabs.NetworkPrefabsLists.Count == 1); - Assert.IsTrue(networkManager.NetworkConfig.Prefabs.NetworkPrefabsLists[0] == null); - Assert.IsTrue(networkManager.NetworkConfig.Prefabs.Prefabs.Count == 0); - } - finally - { - networkManager.ShutdownInternal(); - // Shutdown doesn't get called correctly because we called Initialize() - // instead of calling StartHost/StartClient/StartServer. See MTT-860 for - // why. - networkManager.NetworkConfig?.NetworkTransport.Shutdown(); - } + networkConfig.InitializePrefabs(); + + Assert.IsTrue(networkConfig.Prefabs.NetworkPrefabsLists.Count == 1); + Assert.IsTrue(networkConfig.Prefabs.NetworkPrefabsLists[0] == null); + Assert.IsTrue(networkConfig.Prefabs.Prefabs.Count == 0); + + networkConfig.Prefabs.Shutdown(); } [Test] From 84f59f3e69aee7cf603a858763a384137ac2e8cf Mon Sep 17 00:00:00 2001 From: Larus Olafsson Date: Fri, 24 Oct 2025 14:03:41 +0000 Subject: [PATCH 9/9] remove uninitialized from list instead of ignoring --- .../Runtime/Configuration/NetworkPrefabs.cs | 13 +------------ .../Editor/NetworkManagerConfigurationTests.cs | 4 ++-- 2 files changed, 3 insertions(+), 14 deletions(-) diff --git a/com.unity.netcode.gameobjects/Runtime/Configuration/NetworkPrefabs.cs b/com.unity.netcode.gameobjects/Runtime/Configuration/NetworkPrefabs.cs index ceecb875a9..45d93ad9d7 100644 --- a/com.unity.netcode.gameobjects/Runtime/Configuration/NetworkPrefabs.cs +++ b/com.unity.netcode.gameobjects/Runtime/Configuration/NetworkPrefabs.cs @@ -81,10 +81,6 @@ internal void Shutdown() { foreach (var list in NetworkPrefabsLists) { - if (list == null) - { - continue; - } list.OnAdd -= AddTriggeredByNetworkPrefabList; list.OnRemove -= RemoveTriggeredByNetworkPrefabList; } @@ -98,12 +94,9 @@ internal void Shutdown() public void Initialize(bool warnInvalid = true) { m_Prefabs.Clear(); + NetworkPrefabsLists.RemoveAll(x => x == null); foreach (var list in NetworkPrefabsLists) { - if (list == null) - { - continue; - } list.OnAdd += AddTriggeredByNetworkPrefabList; list.OnRemove += RemoveTriggeredByNetworkPrefabList; } @@ -117,10 +110,6 @@ public void Initialize(bool warnInvalid = true) { foreach (var list in NetworkPrefabsLists) { - if (list == null) - { - continue; - } prefabs.AddRange(list.PrefabList); } } diff --git a/com.unity.netcode.gameobjects/Tests/Editor/NetworkManagerConfigurationTests.cs b/com.unity.netcode.gameobjects/Tests/Editor/NetworkManagerConfigurationTests.cs index 3dbb431d20..d3dd92de2d 100644 --- a/com.unity.netcode.gameobjects/Tests/Editor/NetworkManagerConfigurationTests.cs +++ b/com.unity.netcode.gameobjects/Tests/Editor/NetworkManagerConfigurationTests.cs @@ -303,8 +303,8 @@ public void WhenThereAreUninitializedElementsInPrefabsList_NoErrors() networkConfig.InitializePrefabs(); - Assert.IsTrue(networkConfig.Prefabs.NetworkPrefabsLists.Count == 1); - Assert.IsTrue(networkConfig.Prefabs.NetworkPrefabsLists[0] == null); + // Null elements will be removed from the list so it should be empty + Assert.IsTrue(networkConfig.Prefabs.NetworkPrefabsLists.Count == 0); Assert.IsTrue(networkConfig.Prefabs.Prefabs.Count == 0); networkConfig.Prefabs.Shutdown();