diff --git a/com.unity.netcode.gameobjects/CHANGELOG.md b/com.unity.netcode.gameobjects/CHANGELOG.md index 49bf56231a..1c61b218a9 100644 --- a/com.unity.netcode.gameobjects/CHANGELOG.md +++ b/com.unity.netcode.gameobjects/CHANGELOG.md @@ -22,6 +22,7 @@ Additional documentation and release notes are available at [Multiplayer Documen ### Fixed +- NestedNetworkVariables initialized with no value no longer throw an error. (#3891) ### Security diff --git a/com.unity.netcode.gameobjects/Runtime/NetworkVariable/Serialization/CollectionSerializationUtility.cs b/com.unity.netcode.gameobjects/Runtime/NetworkVariable/Serialization/CollectionSerializationUtility.cs index e8c61ceea7..d9327f2441 100644 --- a/com.unity.netcode.gameobjects/Runtime/NetworkVariable/Serialization/CollectionSerializationUtility.cs +++ b/com.unity.netcode.gameobjects/Runtime/NetworkVariable/Serialization/CollectionSerializationUtility.cs @@ -281,7 +281,7 @@ public static List GetChangedList() } } - public static void WriteHashSetDelta(FastBufferWriter writer, ref HashSet value, ref HashSet previousValue) where T : IEquatable + public static void WriteHashSetDelta(FastBufferWriter writer, ref HashSet value, ref HashSet previousValue) { // HashSets can be null, so we have to handle that case. // We do that by marking this as a full serialization and using the existing null handling logic @@ -337,7 +337,7 @@ public static void WriteHashSetDelta(FastBufferWriter writer, ref HashSet } } - public static void ReadHashSetDelta(FastBufferReader reader, ref HashSet value) where T : IEquatable + public static void ReadHashSetDelta(FastBufferReader reader, ref HashSet value) { // 1 = full serialization, 0 = delta serialization reader.ReadByteSafe(out byte full); diff --git a/com.unity.netcode.gameobjects/Runtime/NetworkVariable/Serialization/TypedILPPInitializers.cs b/com.unity.netcode.gameobjects/Runtime/NetworkVariable/Serialization/TypedILPPInitializers.cs index 8a639258da..9fd42b2ae3 100644 --- a/com.unity.netcode.gameobjects/Runtime/NetworkVariable/Serialization/TypedILPPInitializers.cs +++ b/com.unity.netcode.gameobjects/Runtime/NetworkVariable/Serialization/TypedILPPInitializers.cs @@ -103,7 +103,7 @@ public static void InitializeSerializer_List() /// Registeres a native hash set (this generic implementation works with all types) /// /// The type of elements contained in the HashSet, must implement IEquatable - public static void InitializeSerializer_HashSet() where T : IEquatable + public static void InitializeSerializer_HashSet() { NetworkVariableSerialization>.Serializer = new HashSetSerializer(); } diff --git a/com.unity.netcode.gameobjects/Runtime/NetworkVariable/Serialization/TypedSerializerImplementations.cs b/com.unity.netcode.gameobjects/Runtime/NetworkVariable/Serialization/TypedSerializerImplementations.cs index 49e7e5e7cf..e1242378dd 100644 --- a/com.unity.netcode.gameobjects/Runtime/NetworkVariable/Serialization/TypedSerializerImplementations.cs +++ b/com.unity.netcode.gameobjects/Runtime/NetworkVariable/Serialization/TypedSerializerImplementations.cs @@ -335,6 +335,12 @@ void INetworkVariableSerializer>.ReadWithAllocator(FastBufferReader read public void Duplicate(in List value, ref List duplicatedValue) { + if (value == null) + { + duplicatedValue = null; + return; + } + if (duplicatedValue == null) { duplicatedValue = new List(); @@ -351,7 +357,7 @@ public void Duplicate(in List value, ref List duplicatedValue) } } - internal class HashSetSerializer : INetworkVariableSerializer> where T : IEquatable + internal class HashSetSerializer : INetworkVariableSerializer> { public void Write(FastBufferWriter writer, ref HashSet value) { @@ -414,6 +420,12 @@ void INetworkVariableSerializer>.ReadWithAllocator(FastBufferReader r public void Duplicate(in HashSet value, ref HashSet duplicatedValue) { + if (value == null) + { + duplicatedValue = null; + return; + } + if (duplicatedValue == null) { duplicatedValue = new HashSet(); @@ -496,6 +508,12 @@ void INetworkVariableSerializer>.ReadWithAllocator(FastBu public void Duplicate(in Dictionary value, ref Dictionary duplicatedValue) { + if (value == null) + { + duplicatedValue = null; + return; + } + if (duplicatedValue == null) { duplicatedValue = new Dictionary(); diff --git a/com.unity.netcode.gameobjects/Tests/Runtime/NetworkVariable/NetworkVariableCollectionsTests.cs b/com.unity.netcode.gameobjects/Tests/Runtime/NetworkVariable/NetworkVariableCollectionsTests.cs index 0154e4d6de..69e8727f27 100644 --- a/com.unity.netcode.gameobjects/Tests/Runtime/NetworkVariable/NetworkVariableCollectionsTests.cs +++ b/com.unity.netcode.gameobjects/Tests/Runtime/NetworkVariable/NetworkVariableCollectionsTests.cs @@ -1221,6 +1221,9 @@ public static void ResetState() public NetworkVariable> ListCollectionServer = new NetworkVariable>(new HashSet(), NetworkVariableReadPermission.Everyone, NetworkVariableWritePermission.Server); public NetworkVariable> ListCollectionOwner = new NetworkVariable>(new HashSet(), NetworkVariableReadPermission.Everyone, NetworkVariableWritePermission.Owner); + public NetworkVariable> UninitializedHashSet; + public NetworkVariable>> UninitializedNestedHashSet; + // This tracks what has changed per instance which is used to compare to all other instances internal Dictionary>> NetworkVariableChanges = new Dictionary>>(); @@ -1470,6 +1473,8 @@ public static void ResetState() public NetworkVariable>> ListCollectionServer = new NetworkVariable>>(new Dictionary>(), NetworkVariableReadPermission.Everyone, NetworkVariableWritePermission.Server); public NetworkVariable>> ListCollectionOwner = new NetworkVariable>>(new Dictionary>(), NetworkVariableReadPermission.Everyone, NetworkVariableWritePermission.Owner); + public NetworkVariable>> UninitializedNestedDictionary; + // This tracks what has changed per instance which is used to compare to all other instances internal Dictionary>>> NetworkVariableChanges = new Dictionary>>>(); @@ -1777,6 +1782,8 @@ public static void ResetState() public NetworkVariable> ListCollectionServer = new NetworkVariable>(new Dictionary(), NetworkVariableReadPermission.Everyone, NetworkVariableWritePermission.Server); public NetworkVariable> ListCollectionOwner = new NetworkVariable>(new Dictionary(), NetworkVariableReadPermission.Everyone, NetworkVariableWritePermission.Owner); + public NetworkVariable> UninitializedDictionary; + // This tracks what has changed per instance which is used to compare to all other instances internal Dictionary>> NetworkVariableChanges = new Dictionary>>(); @@ -2144,6 +2151,8 @@ public static void ResetState() public NetworkVariable>> ListCollectionServer = new NetworkVariable>>(new List>(), NetworkVariableReadPermission.Everyone, NetworkVariableWritePermission.Server); public NetworkVariable>> ListCollectionOwner = new NetworkVariable>>(new List>(), NetworkVariableReadPermission.Everyone, NetworkVariableWritePermission.Owner); + public NetworkVariable>> UninitializedNestedList; + // This tracks what has changed per instance which is used to compare to all other instances internal Dictionary>>> NetworkVariableChanges = new Dictionary>>>(); @@ -2443,6 +2452,8 @@ public static void ResetState() public NetworkVariable> ListCollectionServer = new NetworkVariable>(new List(), NetworkVariableReadPermission.Everyone, NetworkVariableWritePermission.Server); public NetworkVariable> ListCollectionOwner = new NetworkVariable>(new List(), NetworkVariableReadPermission.Everyone, NetworkVariableWritePermission.Owner); + public NetworkVariable> UninitializedList; + // This tracks what has changed per instance which is used to compare to all other instances internal Dictionary>> NetworkVariableChanges = new Dictionary>>(); @@ -2708,6 +2719,8 @@ public static void ResetState() public NetworkVariable>> ListCollectionServer = new NetworkVariable>>(new List>(), NetworkVariableReadPermission.Everyone, NetworkVariableWritePermission.Server); public NetworkVariable>> ListCollectionOwner = new NetworkVariable>>(new List>(), NetworkVariableReadPermission.Everyone, NetworkVariableWritePermission.Owner); + public NetworkVariable>> UninitializedList; + // This tracks what has changed per instance which is used to compare to all other instances internal Dictionary>>> NetworkVariableChanges = new Dictionary>>>(); @@ -3012,6 +3025,8 @@ public static void ResetState() public NetworkVariable> ListCollectionServer = new NetworkVariable>(new List(), NetworkVariableReadPermission.Everyone, NetworkVariableWritePermission.Server); public NetworkVariable> ListCollectionOwner = new NetworkVariable>(new List(), NetworkVariableReadPermission.Everyone, NetworkVariableWritePermission.Owner); + public NetworkVariable> UninitializedList; + // This tracks what has changed per instance which is used to compare to all other instances internal Dictionary>> NetworkVariableChanges = new Dictionary>>();