Skip to content

Commit 17320e0

Browse files
fix: ensure server netvar initialization in OnNetworkSpawn replicates correctly to clients as initialization and not delta (#1266)
Co-authored-by: Matt Walsh <[email protected]>
1 parent 1f4b894 commit 17320e0

File tree

5 files changed

+136
-1
lines changed

5 files changed

+136
-1
lines changed

com.unity.netcode.gameobjects/Runtime/Spawning/NetworkSpawnManager.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -413,7 +413,7 @@ internal void SendSpawnCallForObject(ulong clientId, NetworkObject networkObject
413413

414414
var message = new CreateObjectMessage
415415
{
416-
ObjectInfo = networkObject.GetMessageSceneObject(clientId, false)
416+
ObjectInfo = networkObject.GetMessageSceneObject(clientId)
417417
};
418418
var size = NetworkManager.SendMessage(message, NetworkDelivery.ReliableFragmentedSequenced, clientId);
419419
NetworkManager.NetworkMetrics.TrackObjectSpawnSent(clientId, networkObject.NetworkObjectId, networkObject.name, size);
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
using System.Collections;
2+
using NUnit.Framework;
3+
using TestProject.RuntimeTests.Support;
4+
using Unity.Netcode;
5+
using Unity.Netcode.RuntimeTests;
6+
using UnityEngine;
7+
using UnityEngine.TestTools;
8+
9+
namespace TestProject.RuntimeTests
10+
{
11+
public class NetworkVariableInitializationOnNetworkSpawnTest
12+
{
13+
private GameObject m_Prefab;
14+
15+
[UnitySetUp]
16+
public IEnumerator SetUp()
17+
{
18+
// Make sure these static values are reset
19+
NetworkVariableInitOnNetworkSpawn.NetworkSpawnCalledOnClient = false;
20+
NetworkVariableInitOnNetworkSpawn.NetworkSpawnCalledOnServer = false;
21+
yield break;
22+
}
23+
24+
[UnityTearDown]
25+
public IEnumerator Teardown()
26+
{
27+
// Shutdown and clean up both of our NetworkManager instances
28+
if (m_Prefab)
29+
{
30+
MultiInstanceHelpers.Destroy();
31+
Object.Destroy(m_Prefab);
32+
m_Prefab = null;
33+
}
34+
NetworkVariableInitOnNetworkSpawn.NetworkSpawnCalledOnClient = false;
35+
NetworkVariableInitOnNetworkSpawn.NetworkSpawnCalledOnServer = false;
36+
yield break;
37+
}
38+
39+
[UnityTest]
40+
[Description("When a network variable is initialized in OnNetworkSpawn on the server, the spawned object's NetworkVariable on the client is initialized with the same value.")]
41+
public IEnumerator WhenANetworkVariableIsInitializedInOnNetworkSpawnOnTheServer_TheSpawnedObjectsNetworkVariableOnTheClientIsInitializedWithTheSameValue()
42+
{
43+
const int numClients = 1;
44+
Assert.True(MultiInstanceHelpers.Create(numClients, out NetworkManager server, out NetworkManager[] clients));
45+
m_Prefab = new GameObject("Object");
46+
var networkObject = m_Prefab.AddComponent<NetworkObject>();
47+
m_Prefab.AddComponent<NetworkVariableInitOnNetworkSpawn>();
48+
49+
// Make it a prefab
50+
MultiInstanceHelpers.MakeNetworkObjectTestPrefab(networkObject);
51+
52+
var validNetworkPrefab = new NetworkPrefab();
53+
validNetworkPrefab.Prefab = m_Prefab;
54+
server.NetworkConfig.NetworkPrefabs.Add(validNetworkPrefab);
55+
foreach (var client in clients)
56+
{
57+
client.NetworkConfig.NetworkPrefabs.Add(validNetworkPrefab);
58+
}
59+
60+
// Start the instances
61+
if (!MultiInstanceHelpers.Start(true, server, clients))
62+
{
63+
Debug.LogError("Failed to start instances");
64+
Assert.Fail("Failed to start instances");
65+
}
66+
67+
// [Client-Side] Wait for a connection to the server
68+
yield return MultiInstanceHelpers.Run(MultiInstanceHelpers.WaitForClientsConnected(clients, null, 512));
69+
70+
// [Host-Side] Check to make sure all clients are connected
71+
yield return MultiInstanceHelpers.Run(
72+
MultiInstanceHelpers.WaitForClientsConnectedToServer(server, clients.Length + 1, null, 512));
73+
74+
var serverObject = Object.Instantiate(m_Prefab, Vector3.zero, Quaternion.identity);
75+
NetworkObject serverNetworkObject = serverObject.GetComponent<NetworkObject>();
76+
serverNetworkObject.NetworkManagerOwner = server;
77+
serverNetworkObject.Spawn();
78+
79+
// Wait until all objects have spawned.
80+
const int expectedNetworkObjects = numClients + 2; // +2 = one for prefab, one for server.
81+
const int maxFrames = 240;
82+
var doubleCheckTime = Time.realtimeSinceStartup + 5.0f;
83+
while (Object.FindObjectsOfType<NetworkObject>().Length != expectedNetworkObjects)
84+
{
85+
if (Time.frameCount > maxFrames)
86+
{
87+
// This is here in the event a platform is running at a higher
88+
// frame rate than expected
89+
if (doubleCheckTime < Time.realtimeSinceStartup)
90+
{
91+
Assert.Fail("Did not successfully spawn all expected NetworkObjects");
92+
break;
93+
}
94+
}
95+
var nextFrameNumber = Time.frameCount + 1;
96+
yield return new WaitUntil(() => Time.frameCount >= nextFrameNumber);
97+
}
98+
Assert.IsTrue(NetworkVariableInitOnNetworkSpawn.NetworkSpawnCalledOnServer);
99+
Assert.IsTrue(NetworkVariableInitOnNetworkSpawn.NetworkSpawnCalledOnClient);
100+
}
101+
}
102+
}

testproject/Assets/Tests/Runtime/NetworkVariableInitializationOnNetworkSpawnTest.cs.meta

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
using Unity.Netcode;
2+
using NUnit.Framework;
3+
4+
namespace TestProject.RuntimeTests.Support
5+
{
6+
public class NetworkVariableInitOnNetworkSpawn : NetworkBehaviour
7+
{
8+
private NetworkVariable<int> m_Variable = new NetworkVariable<int>();
9+
public static bool NetworkSpawnCalledOnServer;
10+
public static bool NetworkSpawnCalledOnClient;
11+
12+
public override void OnNetworkSpawn()
13+
{
14+
base.OnNetworkSpawn();
15+
if (IsServer)
16+
{
17+
NetworkSpawnCalledOnServer = true;
18+
m_Variable.Value = 5;
19+
}
20+
else
21+
{
22+
NetworkSpawnCalledOnClient = true;
23+
}
24+
Assert.AreEqual(5, m_Variable.Value);
25+
}
26+
}
27+
}

testproject/Assets/Tests/Runtime/Support/NetworkVariableInitOnNetworkSpawn.cs.meta

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)