From 04a6b54a3f497b9d4888b92dd43c107d81cdc3f5 Mon Sep 17 00:00:00 2001 From: PitouGames Date: Sun, 30 Apr 2023 23:36:04 +0200 Subject: [PATCH 1/7] fix: avoid throwing exception when using NetworkList without a NetworkManager (#2539) --- com.unity.netcode.gameobjects/CHANGELOG.md | 1 + .../NetworkVariable/Collections/NetworkList.cs | 12 ++++++------ 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/com.unity.netcode.gameobjects/CHANGELOG.md b/com.unity.netcode.gameobjects/CHANGELOG.md index f902782de2..d93a572b6e 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 issue where invoking `NetworkObject.NetworkShow` and `NetworkObject.ChangeOwnership` consecutively within the same call stack location could result in an unnecessary change in ownership error message generated on the target client side. (#3493) - Fixed issue where `NetworkVariable`s on a `NetworkBehaviour` could fail to synchronize changes if one has `NetworkVariableUpdateTraits` set and is dirty but is not ready to send. (#3465) - Fixed issue where when a client changes ownership via RPC the `NetworkBehaviour.OnOwnershipChanged` can result in identical previous and current owner identifiers. (#3434) +- Fixed `NullReferenceException` on `NetworkList` when used without a NetworkManager in scene. (#2539) ### Changed diff --git a/com.unity.netcode.gameobjects/Runtime/NetworkVariable/Collections/NetworkList.cs b/com.unity.netcode.gameobjects/Runtime/NetworkVariable/Collections/NetworkList.cs index eaf06bbb67..163daed1f3 100644 --- a/com.unity.netcode.gameobjects/Runtime/NetworkVariable/Collections/NetworkList.cs +++ b/com.unity.netcode.gameobjects/Runtime/NetworkVariable/Collections/NetworkList.cs @@ -425,7 +425,7 @@ public IEnumerator GetEnumerator() public void Add(T item) { // check write permissions - if (!CanClientWrite(m_NetworkBehaviour.NetworkManager.LocalClientId)) + if (m_NetworkManager && !CanClientWrite(m_NetworkManager.LocalClientId)) { LogWritePermissionError(); return; @@ -452,7 +452,7 @@ public void Add(T item) public void Clear() { // check write permissions - if (!CanClientWrite(m_NetworkBehaviour.NetworkManager.LocalClientId)) + if (m_NetworkManager && !CanClientWrite(m_NetworkManager.LocalClientId)) { LogWritePermissionError(); return; @@ -490,7 +490,7 @@ public bool Contains(T item) public bool Remove(T item) { // check write permissions - if (!CanClientWrite(m_NetworkBehaviour.NetworkManager.LocalClientId)) + if (m_NetworkManager && !CanClientWrite(m_NetworkManager.LocalClientId)) { LogWritePermissionError(); return false; @@ -539,7 +539,7 @@ public int IndexOf(T item) public void Insert(int index, T item) { // check write permissions - if (!CanClientWrite(m_NetworkBehaviour.NetworkManager.LocalClientId)) + if (m_NetworkManager && !CanClientWrite(m_NetworkManager.LocalClientId)) { LogWritePermissionError(); return; @@ -575,7 +575,7 @@ public void Insert(int index, T item) public void RemoveAt(int index) { // check write permissions - if (!CanClientWrite(m_NetworkBehaviour.NetworkManager.LocalClientId)) + if (m_NetworkManager && !CanClientWrite(m_NetworkManager.LocalClientId)) { LogWritePermissionError(); return; @@ -608,7 +608,7 @@ public T this[int index] set { // check write permissions - if (!CanClientWrite(m_NetworkBehaviour.NetworkManager.LocalClientId)) + if (m_NetworkManager && !CanClientWrite(m_NetworkManager.LocalClientId)) { LogWritePermissionError(); return; From 7bb6e7e482c5ca5d4bd277eadfe9d7daf5c80478 Mon Sep 17 00:00:00 2001 From: Emma Date: Fri, 13 Jun 2025 16:52:18 -0400 Subject: [PATCH 2/7] Refactor into shared logic --- com.unity.netcode.gameobjects/CHANGELOG.md | 2 +- .../NetworkVariable/Collections/NetworkList.cs | 12 ++++++------ .../Runtime/NetworkVariable/NetworkVariable.cs | 14 +++++++------- .../Runtime/NetworkVariable/NetworkVariableBase.cs | 5 +++++ 4 files changed, 19 insertions(+), 14 deletions(-) diff --git a/com.unity.netcode.gameobjects/CHANGELOG.md b/com.unity.netcode.gameobjects/CHANGELOG.md index d93a572b6e..89c3f0d2f4 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 ### Fixed +- Fixed `NullReferenceException` on `NetworkList` when used without a NetworkManager in scene. (#2539) - Fixed inconsistencies in the `OnSceneEvent` callback. (#3487) - Fixed issue where `NetworkClient` could persist some settings if re-using the same `NetworkManager` instance. (#3494) - Fixed issue where a pooled `NetworkObject` was not resetting the internal latest parent property when despawned. (#3494) @@ -22,7 +23,6 @@ Additional documentation and release notes are available at [Multiplayer Documen - Fixed issue where invoking `NetworkObject.NetworkShow` and `NetworkObject.ChangeOwnership` consecutively within the same call stack location could result in an unnecessary change in ownership error message generated on the target client side. (#3493) - Fixed issue where `NetworkVariable`s on a `NetworkBehaviour` could fail to synchronize changes if one has `NetworkVariableUpdateTraits` set and is dirty but is not ready to send. (#3465) - Fixed issue where when a client changes ownership via RPC the `NetworkBehaviour.OnOwnershipChanged` can result in identical previous and current owner identifiers. (#3434) -- Fixed `NullReferenceException` on `NetworkList` when used without a NetworkManager in scene. (#2539) ### Changed diff --git a/com.unity.netcode.gameobjects/Runtime/NetworkVariable/Collections/NetworkList.cs b/com.unity.netcode.gameobjects/Runtime/NetworkVariable/Collections/NetworkList.cs index 163daed1f3..87ad616e38 100644 --- a/com.unity.netcode.gameobjects/Runtime/NetworkVariable/Collections/NetworkList.cs +++ b/com.unity.netcode.gameobjects/Runtime/NetworkVariable/Collections/NetworkList.cs @@ -425,7 +425,7 @@ public IEnumerator GetEnumerator() public void Add(T item) { // check write permissions - if (m_NetworkManager && !CanClientWrite(m_NetworkManager.LocalClientId)) + if (LocalClientCannotWrite()) { LogWritePermissionError(); return; @@ -452,7 +452,7 @@ public void Add(T item) public void Clear() { // check write permissions - if (m_NetworkManager && !CanClientWrite(m_NetworkManager.LocalClientId)) + if (LocalClientCannotWrite()) { LogWritePermissionError(); return; @@ -490,7 +490,7 @@ public bool Contains(T item) public bool Remove(T item) { // check write permissions - if (m_NetworkManager && !CanClientWrite(m_NetworkManager.LocalClientId)) + if (LocalClientCannotWrite()) { LogWritePermissionError(); return false; @@ -539,7 +539,7 @@ public int IndexOf(T item) public void Insert(int index, T item) { // check write permissions - if (m_NetworkManager && !CanClientWrite(m_NetworkManager.LocalClientId)) + if (LocalClientCannotWrite()) { LogWritePermissionError(); return; @@ -575,7 +575,7 @@ public void Insert(int index, T item) public void RemoveAt(int index) { // check write permissions - if (m_NetworkManager && !CanClientWrite(m_NetworkManager.LocalClientId)) + if (LocalClientCannotWrite()) { LogWritePermissionError(); return; @@ -608,7 +608,7 @@ public T this[int index] set { // check write permissions - if (m_NetworkManager && !CanClientWrite(m_NetworkManager.LocalClientId)) + if (LocalClientCannotWrite()) { LogWritePermissionError(); return; diff --git a/com.unity.netcode.gameobjects/Runtime/NetworkVariable/NetworkVariable.cs b/com.unity.netcode.gameobjects/Runtime/NetworkVariable/NetworkVariable.cs index 5df83215b1..6e5c3cbad4 100644 --- a/com.unity.netcode.gameobjects/Runtime/NetworkVariable/NetworkVariable.cs +++ b/com.unity.netcode.gameobjects/Runtime/NetworkVariable/NetworkVariable.cs @@ -90,7 +90,7 @@ public void Reset(T value = default) // The introduction of standard .NET collections caused an issue with permissions since there is no way to detect changes in the // collection without doing a full comparison. While this approach does consume more memory per collection instance, it is the // lowest risk approach to resolving the issue where a client with no write permissions could make changes to a collection locally - // which can cause a myriad of issues. + // which can cause a myriad of issues. private protected T m_InternalOriginalValue; private protected T m_PreviousValue; @@ -112,7 +112,7 @@ public virtual T Value get => m_InternalValue; set { - if (m_NetworkManager && !CanClientWrite(m_NetworkManager.LocalClientId)) + if (LocalClientCannotWrite()) { LogWritePermissionError(); return; @@ -145,7 +145,7 @@ public bool CheckDirtyState(bool forceCheck = false) var isDirty = base.IsDirty(); // A client without permissions invoking this method should only check to assure the current value is equal to the last known current value - if (m_NetworkManager && !CanClientWrite(m_NetworkManager.LocalClientId)) + if (LocalClientCannotWrite()) { // If modifications are detected, then revert back to the last known current value if (!NetworkVariableSerialization.AreEqual(ref m_InternalValue, ref m_InternalOriginalValue)) @@ -221,7 +221,7 @@ public override bool IsDirty() { // If the client does not have write permissions but the internal value is determined to be locally modified and we are applying updates, then we should revert // to the original collection value prior to applying updates (primarily for collections). - if (!NetworkUpdaterCheck && m_NetworkManager && !CanClientWrite(m_NetworkManager.LocalClientId) && !NetworkVariableSerialization.AreEqual(ref m_InternalValue, ref m_InternalOriginalValue)) + if (!NetworkUpdaterCheck && LocalClientCannotWrite() && !NetworkVariableSerialization.AreEqual(ref m_InternalValue, ref m_InternalOriginalValue)) { NetworkVariableSerialization.Duplicate(m_InternalOriginalValue, ref m_InternalValue); return true; @@ -297,7 +297,7 @@ public override void ReadDelta(FastBufferReader reader, bool keepDirtyDelta) { // If the client does not have write permissions but the internal value is determined to be locally modified and we are applying updates, then we should revert // to the original collection value prior to applying updates (primarily for collections). - if (m_NetworkManager && !CanClientWrite(m_NetworkManager.LocalClientId) && !NetworkVariableSerialization.AreEqual(ref m_InternalOriginalValue, ref m_InternalValue)) + if (LocalCLientCannotWrite() && !NetworkVariableSerialization.AreEqual(ref m_InternalOriginalValue, ref m_InternalValue)) { NetworkVariableSerialization.Duplicate(m_InternalOriginalValue, ref m_InternalValue); } @@ -320,7 +320,7 @@ public override void ReadDelta(FastBufferReader reader, bool keepDirtyDelta) /// This should be always invoked (client & server) to assure the previous values are set /// !! IMPORTANT !! /// When a server forwards delta updates to connected clients, it needs to preserve the previous dirty value(s) - /// until it is done serializing all valid NetworkVariable field deltas (relative to each client). This is invoked + /// until it is done serializing all valid NetworkVariable field deltas (relative to each client). This is invoked /// after it is done forwarding the deltas at the end of the method. /// internal override void PostDeltaRead() @@ -338,7 +338,7 @@ public override void ReadField(FastBufferReader reader) { // If the client does not have write permissions but the internal value is determined to be locally modified and we are applying updates, then we should revert // to the original collection value prior to applying updates (primarily for collections). - if (m_NetworkManager && !CanClientWrite(m_NetworkManager.LocalClientId) && !NetworkVariableSerialization.AreEqual(ref m_InternalOriginalValue, ref m_InternalValue)) + if (LocalClientCannotWrite() && !NetworkVariableSerialization.AreEqual(ref m_InternalOriginalValue, ref m_InternalValue)) { NetworkVariableSerialization.Duplicate(m_InternalOriginalValue, ref m_InternalValue); } diff --git a/com.unity.netcode.gameobjects/Runtime/NetworkVariable/NetworkVariableBase.cs b/com.unity.netcode.gameobjects/Runtime/NetworkVariable/NetworkVariableBase.cs index 377fadeee0..03c9c5564e 100644 --- a/com.unity.netcode.gameobjects/Runtime/NetworkVariable/NetworkVariableBase.cs +++ b/com.unity.netcode.gameobjects/Runtime/NetworkVariable/NetworkVariableBase.cs @@ -337,6 +337,11 @@ public bool CanClientWrite(ulong clientId) } } + internal bool LocalClientCannotWrite() + { + return m_NetworkManager && !CanClientWrite(m_NetworkManager.LocalClientId); + } + /// /// Returns the ClientId of the owning client /// From 919302b56318ea49b6e636489dc97af283711539 Mon Sep 17 00:00:00 2001 From: Emma Date: Fri, 13 Jun 2025 17:04:26 -0400 Subject: [PATCH 3/7] Add inlining and code docs --- .../Runtime/NetworkVariable/NetworkVariableBase.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/com.unity.netcode.gameobjects/Runtime/NetworkVariable/NetworkVariableBase.cs b/com.unity.netcode.gameobjects/Runtime/NetworkVariable/NetworkVariableBase.cs index 03c9c5564e..d427abf01a 100644 --- a/com.unity.netcode.gameobjects/Runtime/NetworkVariable/NetworkVariableBase.cs +++ b/com.unity.netcode.gameobjects/Runtime/NetworkVariable/NetworkVariableBase.cs @@ -1,4 +1,5 @@ using System; +using System.Runtime.CompilerServices; using UnityEngine; namespace Unity.Netcode @@ -336,7 +337,11 @@ public bool CanClientWrite(ulong clientId) return clientId == m_NetworkBehaviour.NetworkObject.OwnerClientId; } } - + /// + /// Catches if the current is not valid to write to this variable. + /// + /// false if the current can write to this variable, true otherwise + [MethodImpl(MethodImplOptions.AggressiveInlining)] internal bool LocalClientCannotWrite() { return m_NetworkManager && !CanClientWrite(m_NetworkManager.LocalClientId); From ce3787b6446b51dc68523e8f20fe7bea46a4e4ce Mon Sep 17 00:00:00 2001 From: Emma Date: Fri, 13 Jun 2025 17:32:21 -0400 Subject: [PATCH 4/7] Update naming, add CanWrite method --- .../Messages/NetworkVariableDeltaMessage.cs | 2 +- .../NetworkVariable/AnticipatedNetworkVariable.cs | 2 +- .../Runtime/NetworkVariable/NetworkVariable.cs | 10 +++++----- .../NetworkVariable/NetworkVariableBase.cs | 15 ++++++++------- 4 files changed, 15 insertions(+), 14 deletions(-) diff --git a/com.unity.netcode.gameobjects/Runtime/Messaging/Messages/NetworkVariableDeltaMessage.cs b/com.unity.netcode.gameobjects/Runtime/Messaging/Messages/NetworkVariableDeltaMessage.cs index 7331c28e4c..9d52523067 100644 --- a/com.unity.netcode.gameobjects/Runtime/Messaging/Messages/NetworkVariableDeltaMessage.cs +++ b/com.unity.netcode.gameobjects/Runtime/Messaging/Messages/NetworkVariableDeltaMessage.cs @@ -145,7 +145,7 @@ public void Serialize(FastBufferWriter writer, int targetVersion) var networkVariable = NetworkBehaviour.NetworkVariableFields[i]; var shouldWrite = networkVariable.IsDirty() && networkVariable.CanClientRead(TargetClientId) && - (networkManager.IsServer || networkVariable.CanClientWrite(networkManager.LocalClientId)) && + (networkManager.IsServer || networkVariable.CanWrite()) && networkVariable.CanSend(); // Prevent the server from writing to the client that owns a given NetworkVariable diff --git a/com.unity.netcode.gameobjects/Runtime/NetworkVariable/AnticipatedNetworkVariable.cs b/com.unity.netcode.gameobjects/Runtime/NetworkVariable/AnticipatedNetworkVariable.cs index 94625722e3..7c25ca5c93 100644 --- a/com.unity.netcode.gameobjects/Runtime/NetworkVariable/AnticipatedNetworkVariable.cs +++ b/com.unity.netcode.gameobjects/Runtime/NetworkVariable/AnticipatedNetworkVariable.cs @@ -189,7 +189,7 @@ public void Anticipate(T value) m_LastAnticipationCounter = m_NetworkBehaviour.NetworkManager.AnticipationSystem.AnticipationCounter; m_AnticipatedValue = value; NetworkVariableSerialization.Duplicate(m_AnticipatedValue, ref m_PreviousAnticipatedValue); - if (CanClientWrite(m_NetworkBehaviour.NetworkManager.LocalClientId)) + if (CanWrite()) { AuthoritativeValue = value; } diff --git a/com.unity.netcode.gameobjects/Runtime/NetworkVariable/NetworkVariable.cs b/com.unity.netcode.gameobjects/Runtime/NetworkVariable/NetworkVariable.cs index 6e5c3cbad4..47fb501615 100644 --- a/com.unity.netcode.gameobjects/Runtime/NetworkVariable/NetworkVariable.cs +++ b/com.unity.netcode.gameobjects/Runtime/NetworkVariable/NetworkVariable.cs @@ -112,7 +112,7 @@ public virtual T Value get => m_InternalValue; set { - if (LocalClientCannotWrite()) + if (CannotWrite()) { LogWritePermissionError(); return; @@ -145,7 +145,7 @@ public bool CheckDirtyState(bool forceCheck = false) var isDirty = base.IsDirty(); // A client without permissions invoking this method should only check to assure the current value is equal to the last known current value - if (LocalClientCannotWrite()) + if (CannotWrite()) { // If modifications are detected, then revert back to the last known current value if (!NetworkVariableSerialization.AreEqual(ref m_InternalValue, ref m_InternalOriginalValue)) @@ -221,7 +221,7 @@ public override bool IsDirty() { // If the client does not have write permissions but the internal value is determined to be locally modified and we are applying updates, then we should revert // to the original collection value prior to applying updates (primarily for collections). - if (!NetworkUpdaterCheck && LocalClientCannotWrite() && !NetworkVariableSerialization.AreEqual(ref m_InternalValue, ref m_InternalOriginalValue)) + if (!NetworkUpdaterCheck && CannotWrite() && !NetworkVariableSerialization.AreEqual(ref m_InternalValue, ref m_InternalOriginalValue)) { NetworkVariableSerialization.Duplicate(m_InternalOriginalValue, ref m_InternalValue); return true; @@ -297,7 +297,7 @@ public override void ReadDelta(FastBufferReader reader, bool keepDirtyDelta) { // If the client does not have write permissions but the internal value is determined to be locally modified and we are applying updates, then we should revert // to the original collection value prior to applying updates (primarily for collections). - if (LocalCLientCannotWrite() && !NetworkVariableSerialization.AreEqual(ref m_InternalOriginalValue, ref m_InternalValue)) + if (CannotWrite() && !NetworkVariableSerialization.AreEqual(ref m_InternalOriginalValue, ref m_InternalValue)) { NetworkVariableSerialization.Duplicate(m_InternalOriginalValue, ref m_InternalValue); } @@ -338,7 +338,7 @@ public override void ReadField(FastBufferReader reader) { // If the client does not have write permissions but the internal value is determined to be locally modified and we are applying updates, then we should revert // to the original collection value prior to applying updates (primarily for collections). - if (LocalClientCannotWrite() && !NetworkVariableSerialization.AreEqual(ref m_InternalOriginalValue, ref m_InternalValue)) + if (CannotWrite() && !NetworkVariableSerialization.AreEqual(ref m_InternalOriginalValue, ref m_InternalValue)) { NetworkVariableSerialization.Duplicate(m_InternalOriginalValue, ref m_InternalValue); } diff --git a/com.unity.netcode.gameobjects/Runtime/NetworkVariable/NetworkVariableBase.cs b/com.unity.netcode.gameobjects/Runtime/NetworkVariable/NetworkVariableBase.cs index d427abf01a..508d4019dd 100644 --- a/com.unity.netcode.gameobjects/Runtime/NetworkVariable/NetworkVariableBase.cs +++ b/com.unity.netcode.gameobjects/Runtime/NetworkVariable/NetworkVariableBase.cs @@ -337,15 +337,16 @@ public bool CanClientWrite(ulong clientId) return clientId == m_NetworkBehaviour.NetworkObject.OwnerClientId; } } + /// - /// Catches if the current is not valid to write to this variable. + /// Returns true if the current can write to this variable; otherwise false. /// - /// false if the current can write to this variable, true otherwise - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal bool LocalClientCannotWrite() - { - return m_NetworkManager && !CanClientWrite(m_NetworkManager.LocalClientId); - } + internal bool CanWrite => m_NetworkManager && CanClientWrite(m_NetworkManager.LocalClientId); + + /// + /// Returns false if the current can write to this variable; otherwise true. + /// + internal bool CannotWrite => m_NetworkManager && !CanClientWrite(m_NetworkManager.LocalClientId); /// /// Returns the ClientId of the owning client From 02f132bef12f936d96d57c78347c97b4784937f4 Mon Sep 17 00:00:00 2001 From: Emma Date: Fri, 13 Jun 2025 17:47:30 -0400 Subject: [PATCH 5/7] style and fix --- .../Messages/NetworkVariableDeltaMessage.cs | 6 +++--- .../NetworkVariable/AnticipatedNetworkVariable.cs | 2 +- .../NetworkVariable/Collections/NetworkList.cs | 12 ++++++------ .../Runtime/NetworkVariable/NetworkVariable.cs | 10 +++++----- .../Runtime/NetworkVariable/NetworkVariableBase.cs | 1 - 5 files changed, 15 insertions(+), 16 deletions(-) diff --git a/com.unity.netcode.gameobjects/Runtime/Messaging/Messages/NetworkVariableDeltaMessage.cs b/com.unity.netcode.gameobjects/Runtime/Messaging/Messages/NetworkVariableDeltaMessage.cs index 9d52523067..beabe167c1 100644 --- a/com.unity.netcode.gameobjects/Runtime/Messaging/Messages/NetworkVariableDeltaMessage.cs +++ b/com.unity.netcode.gameobjects/Runtime/Messaging/Messages/NetworkVariableDeltaMessage.cs @@ -144,9 +144,9 @@ public void Serialize(FastBufferWriter writer, int targetVersion) var startingSize = writer.Length; var networkVariable = NetworkBehaviour.NetworkVariableFields[i]; var shouldWrite = networkVariable.IsDirty() && - networkVariable.CanClientRead(TargetClientId) && - (networkManager.IsServer || networkVariable.CanWrite()) && - networkVariable.CanSend(); + networkVariable.CanClientRead(TargetClientId) + && networkManager.IsServer || + (networkVariable.CanWrite && networkVariable.CanSend()); // Prevent the server from writing to the client that owns a given NetworkVariable // Allowing the write would send an old value to the client and cause jitter diff --git a/com.unity.netcode.gameobjects/Runtime/NetworkVariable/AnticipatedNetworkVariable.cs b/com.unity.netcode.gameobjects/Runtime/NetworkVariable/AnticipatedNetworkVariable.cs index 7c25ca5c93..ac5d7d5323 100644 --- a/com.unity.netcode.gameobjects/Runtime/NetworkVariable/AnticipatedNetworkVariable.cs +++ b/com.unity.netcode.gameobjects/Runtime/NetworkVariable/AnticipatedNetworkVariable.cs @@ -189,7 +189,7 @@ public void Anticipate(T value) m_LastAnticipationCounter = m_NetworkBehaviour.NetworkManager.AnticipationSystem.AnticipationCounter; m_AnticipatedValue = value; NetworkVariableSerialization.Duplicate(m_AnticipatedValue, ref m_PreviousAnticipatedValue); - if (CanWrite()) + if (CanWrite) { AuthoritativeValue = value; } diff --git a/com.unity.netcode.gameobjects/Runtime/NetworkVariable/Collections/NetworkList.cs b/com.unity.netcode.gameobjects/Runtime/NetworkVariable/Collections/NetworkList.cs index 87ad616e38..db7f2023b5 100644 --- a/com.unity.netcode.gameobjects/Runtime/NetworkVariable/Collections/NetworkList.cs +++ b/com.unity.netcode.gameobjects/Runtime/NetworkVariable/Collections/NetworkList.cs @@ -425,7 +425,7 @@ public IEnumerator GetEnumerator() public void Add(T item) { // check write permissions - if (LocalClientCannotWrite()) + if (CannotWrite) { LogWritePermissionError(); return; @@ -452,7 +452,7 @@ public void Add(T item) public void Clear() { // check write permissions - if (LocalClientCannotWrite()) + if (CannotWrite) { LogWritePermissionError(); return; @@ -490,7 +490,7 @@ public bool Contains(T item) public bool Remove(T item) { // check write permissions - if (LocalClientCannotWrite()) + if (CannotWrite) { LogWritePermissionError(); return false; @@ -539,7 +539,7 @@ public int IndexOf(T item) public void Insert(int index, T item) { // check write permissions - if (LocalClientCannotWrite()) + if (CannotWrite) { LogWritePermissionError(); return; @@ -575,7 +575,7 @@ public void Insert(int index, T item) public void RemoveAt(int index) { // check write permissions - if (LocalClientCannotWrite()) + if (CannotWrite) { LogWritePermissionError(); return; @@ -608,7 +608,7 @@ public T this[int index] set { // check write permissions - if (LocalClientCannotWrite()) + if (CannotWrite) { LogWritePermissionError(); return; diff --git a/com.unity.netcode.gameobjects/Runtime/NetworkVariable/NetworkVariable.cs b/com.unity.netcode.gameobjects/Runtime/NetworkVariable/NetworkVariable.cs index 47fb501615..80459c775e 100644 --- a/com.unity.netcode.gameobjects/Runtime/NetworkVariable/NetworkVariable.cs +++ b/com.unity.netcode.gameobjects/Runtime/NetworkVariable/NetworkVariable.cs @@ -112,7 +112,7 @@ public virtual T Value get => m_InternalValue; set { - if (CannotWrite()) + if (CannotWrite) { LogWritePermissionError(); return; @@ -145,7 +145,7 @@ public bool CheckDirtyState(bool forceCheck = false) var isDirty = base.IsDirty(); // A client without permissions invoking this method should only check to assure the current value is equal to the last known current value - if (CannotWrite()) + if (CannotWrite) { // If modifications are detected, then revert back to the last known current value if (!NetworkVariableSerialization.AreEqual(ref m_InternalValue, ref m_InternalOriginalValue)) @@ -221,7 +221,7 @@ public override bool IsDirty() { // If the client does not have write permissions but the internal value is determined to be locally modified and we are applying updates, then we should revert // to the original collection value prior to applying updates (primarily for collections). - if (!NetworkUpdaterCheck && CannotWrite() && !NetworkVariableSerialization.AreEqual(ref m_InternalValue, ref m_InternalOriginalValue)) + if (!NetworkUpdaterCheck && CannotWrite && !NetworkVariableSerialization.AreEqual(ref m_InternalValue, ref m_InternalOriginalValue)) { NetworkVariableSerialization.Duplicate(m_InternalOriginalValue, ref m_InternalValue); return true; @@ -297,7 +297,7 @@ public override void ReadDelta(FastBufferReader reader, bool keepDirtyDelta) { // If the client does not have write permissions but the internal value is determined to be locally modified and we are applying updates, then we should revert // to the original collection value prior to applying updates (primarily for collections). - if (CannotWrite() && !NetworkVariableSerialization.AreEqual(ref m_InternalOriginalValue, ref m_InternalValue)) + if (CannotWrite && !NetworkVariableSerialization.AreEqual(ref m_InternalOriginalValue, ref m_InternalValue)) { NetworkVariableSerialization.Duplicate(m_InternalOriginalValue, ref m_InternalValue); } @@ -338,7 +338,7 @@ public override void ReadField(FastBufferReader reader) { // If the client does not have write permissions but the internal value is determined to be locally modified and we are applying updates, then we should revert // to the original collection value prior to applying updates (primarily for collections). - if (CannotWrite() && !NetworkVariableSerialization.AreEqual(ref m_InternalOriginalValue, ref m_InternalValue)) + if (CannotWrite && !NetworkVariableSerialization.AreEqual(ref m_InternalOriginalValue, ref m_InternalValue)) { NetworkVariableSerialization.Duplicate(m_InternalOriginalValue, ref m_InternalValue); } diff --git a/com.unity.netcode.gameobjects/Runtime/NetworkVariable/NetworkVariableBase.cs b/com.unity.netcode.gameobjects/Runtime/NetworkVariable/NetworkVariableBase.cs index 508d4019dd..19359fc459 100644 --- a/com.unity.netcode.gameobjects/Runtime/NetworkVariable/NetworkVariableBase.cs +++ b/com.unity.netcode.gameobjects/Runtime/NetworkVariable/NetworkVariableBase.cs @@ -1,5 +1,4 @@ using System; -using System.Runtime.CompilerServices; using UnityEngine; namespace Unity.Netcode From b5470ce7603d301417c9373436f9ccffee348797 Mon Sep 17 00:00:00 2001 From: Emma Date: Wed, 18 Jun 2025 15:11:51 -0400 Subject: [PATCH 6/7] Fix tests --- .../Messaging/Messages/NetworkVariableDeltaMessage.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/com.unity.netcode.gameobjects/Runtime/Messaging/Messages/NetworkVariableDeltaMessage.cs b/com.unity.netcode.gameobjects/Runtime/Messaging/Messages/NetworkVariableDeltaMessage.cs index beabe167c1..728041a2f2 100644 --- a/com.unity.netcode.gameobjects/Runtime/Messaging/Messages/NetworkVariableDeltaMessage.cs +++ b/com.unity.netcode.gameobjects/Runtime/Messaging/Messages/NetworkVariableDeltaMessage.cs @@ -144,9 +144,9 @@ public void Serialize(FastBufferWriter writer, int targetVersion) var startingSize = writer.Length; var networkVariable = NetworkBehaviour.NetworkVariableFields[i]; var shouldWrite = networkVariable.IsDirty() && - networkVariable.CanClientRead(TargetClientId) - && networkManager.IsServer || - (networkVariable.CanWrite && networkVariable.CanSend()); + networkVariable.CanClientRead(TargetClientId) && + (networkManager.IsServer || networkVariable.CanWrite) && + networkVariable.CanSend(); // Prevent the server from writing to the client that owns a given NetworkVariable // Allowing the write would send an old value to the client and cause jitter From a20f59f35e672189eabeba26f66e02e3e2d08c41 Mon Sep 17 00:00:00 2001 From: Noel Stephens Date: Mon, 23 Jun 2025 10:45:46 -0500 Subject: [PATCH 7/7] Update CHANGELOG.md Changing the PR number to this PR. --- 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 89c3f0d2f4..d017ffab02 100644 --- a/com.unity.netcode.gameobjects/CHANGELOG.md +++ b/com.unity.netcode.gameobjects/CHANGELOG.md @@ -15,7 +15,7 @@ Additional documentation and release notes are available at [Multiplayer Documen ### Fixed -- Fixed `NullReferenceException` on `NetworkList` when used without a NetworkManager in scene. (#2539) +- Fixed `NullReferenceException` on `NetworkList` when used without a NetworkManager in scene. (#3502) - Fixed inconsistencies in the `OnSceneEvent` callback. (#3487) - Fixed issue where `NetworkClient` could persist some settings if re-using the same `NetworkManager` instance. (#3494) - Fixed issue where a pooled `NetworkObject` was not resetting the internal latest parent property when despawned. (#3494)