Skip to content

Commit b6a68e7

Browse files
authored
fix: mtt-4516 NetworkList change inside OnNetworkSpawn (#2181)
* fix: Marking NetworkVariable dirty upon spawn on the host/server. Falls short as the NetworkBehaviour doesn't yet have its NetworkVariables initialized * fix: clearing variable dirty state post spawning. Also, Initializing NetworkVariable upon spawn, as it is the logical place to do so * test: tests and removing debug logging
1 parent 1e6721c commit b6a68e7

File tree

5 files changed

+51
-30
lines changed

5 files changed

+51
-30
lines changed

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

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -476,6 +476,15 @@ internal void VisibleOnNetworkSpawn()
476476
{
477477
Debug.LogException(e);
478478
}
479+
480+
InitializeVariables();
481+
if (IsServer)
482+
{
483+
// Since we just spawned the object and since user code might have modified their NetworkVariable, esp.
484+
// NetworkList, we need to mark the object as free of updates.
485+
// This should happen for all objects on the machine triggering the spawn.
486+
PostNetworkVariableWrite(true);
487+
}
479488
}
480489

481490
internal void InternalOnNetworkDespawn()
@@ -622,12 +631,24 @@ internal void PreNetworkVariableWrite()
622631
NetworkVariableIndexesToResetSet.Clear();
623632
}
624633

625-
internal void PostNetworkVariableWrite()
634+
internal void PostNetworkVariableWrite(bool forced = false)
626635
{
627-
// mark any variables we wrote as no longer dirty
628-
for (int i = 0; i < NetworkVariableIndexesToReset.Count; i++)
636+
if (forced)
637+
{
638+
// Mark every variable as no longer dirty. We just spawned the object and whatever the game code did
639+
// during OnNetworkSpawn has been sent and needs to be cleared
640+
for (int i = 0; i < NetworkVariableFields.Count; i++)
641+
{
642+
NetworkVariableFields[i].ResetDirty();
643+
}
644+
}
645+
else
629646
{
630-
NetworkVariableFields[NetworkVariableIndexesToReset[i]].ResetDirty();
647+
// mark any variables we wrote as no longer dirty
648+
for (int i = 0; i < NetworkVariableIndexesToReset.Count; i++)
649+
{
650+
NetworkVariableFields[NetworkVariableIndexesToReset[i]].ResetDirty();
651+
}
631652
}
632653

633654
MarkVariablesDirty(false);

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

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -75,10 +75,7 @@ internal void NetworkBehaviourUpdate(NetworkManager networkManager)
7575
// Now, reset all the no-longer-dirty variables
7676
foreach (var dirtyobj in m_DirtyNetworkObjects)
7777
{
78-
for (int k = 0; k < dirtyobj.ChildNetworkBehaviours.Count; k++)
79-
{
80-
dirtyobj.ChildNetworkBehaviours[k].PostNetworkVariableWrite();
81-
}
78+
dirtyobj.PostNetworkVariableWrite();
8279
}
8380
m_DirtyNetworkObjects.Clear();
8481
}

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1094,6 +1094,14 @@ public unsafe void Deserialize(FastBufferReader reader)
10941094
}
10951095
}
10961096

1097+
internal void PostNetworkVariableWrite()
1098+
{
1099+
for (int k = 0; k < ChildNetworkBehaviours.Count; k++)
1100+
{
1101+
ChildNetworkBehaviours[k].PostNetworkVariableWrite();
1102+
}
1103+
}
1104+
10971105
internal SceneObject GetMessageSceneObject(ulong targetClientId)
10981106
{
10991107
var obj = new SceneObject

com.unity.netcode.gameobjects/Runtime/NetworkVariable/Collections/NetworkList.cs

Lines changed: 3 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ namespace Unity.Netcode
1212
public class NetworkList<T> : NetworkVariableBase where T : unmanaged, IEquatable<T>
1313
{
1414
private NativeList<T> m_List = new NativeList<T>(64, Allocator.Persistent);
15-
private NativeList<T> m_ListAtLastReset = new NativeList<T>(64, Allocator.Persistent);
1615
private NativeList<NetworkListEvent<T>> m_DirtyEvents = new NativeList<NetworkListEvent<T>>(64, Allocator.Persistent);
1716

1817
/// <summary>
@@ -53,7 +52,6 @@ public override void ResetDirty()
5352
if (m_DirtyEvents.Length > 0)
5453
{
5554
m_DirtyEvents.Clear();
56-
m_ListAtLastReset.CopyFrom(m_List.AsArray());
5755
}
5856
}
5957

@@ -135,26 +133,10 @@ public override void WriteDelta(FastBufferWriter writer)
135133
/// <inheritdoc />
136134
public override void WriteField(FastBufferWriter writer)
137135
{
138-
// The listAtLastReset mechanism was put in place to deal with duplicate adds
139-
// upon initial spawn. However, it causes issues with in-scene placed objects
140-
// due to difference in spawn order. In order to address this, we pick the right
141-
// list based on the type of object.
142-
bool isSceneObject = m_NetworkBehaviour.NetworkObject.IsSceneObject != false;
143-
if (isSceneObject)
136+
writer.WriteValueSafe((ushort)m_List.Length);
137+
for (int i = 0; i < m_List.Length; i++)
144138
{
145-
writer.WriteValueSafe((ushort)m_ListAtLastReset.Length);
146-
for (int i = 0; i < m_ListAtLastReset.Length; i++)
147-
{
148-
NetworkVariableSerialization<T>.Write(writer, ref m_ListAtLastReset.ElementAt(i));
149-
}
150-
}
151-
else
152-
{
153-
writer.WriteValueSafe((ushort)m_List.Length);
154-
for (int i = 0; i < m_List.Length; i++)
155-
{
156-
NetworkVariableSerialization<T>.Write(writer, ref m_List.ElementAt(i));
157-
}
139+
NetworkVariableSerialization<T>.Write(writer, ref m_List.ElementAt(i));
158140
}
159141
}
160142

@@ -528,7 +510,6 @@ public int LastModifiedTick
528510
public override void Dispose()
529511
{
530512
m_List.Dispose();
531-
m_ListAtLastReset.Dispose();
532513
m_DirtyEvents.Dispose();
533514
}
534515
}

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

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,17 @@ public override void OnNetworkSpawn()
3737
{
3838
ClientTargetedNetworkObjects.Add(this);
3939
}
40+
41+
if (IsServer)
42+
{
43+
MyListSetOnSpawn.Add(45);
44+
}
45+
else
46+
{
47+
Debug.Assert(MyListSetOnSpawn.Count == 1);
48+
Debug.Assert(MyListSetOnSpawn[0] == 45);
49+
}
50+
4051
base.OnNetworkSpawn();
4152
}
4253

@@ -50,11 +61,14 @@ public override void OnNetworkDespawn()
5061
}
5162

5263
public NetworkVariable<int> MyNetworkVariable;
64+
public NetworkList<int> MyListSetOnSpawn;
5365

5466
private void Awake()
5567
{
5668
MyNetworkVariable = new NetworkVariable<int>();
5769
MyNetworkVariable.OnValueChanged += Changed;
70+
71+
MyListSetOnSpawn = new NetworkList<int>();
5872
}
5973

6074
public void Changed(int before, int after)

0 commit comments

Comments
 (0)