|
1 | 1 | using System.Collections; |
| 2 | +using System.Text; |
2 | 3 | using NUnit.Framework; |
3 | 4 | using TestProject.ManualTests; |
4 | 5 | using Unity.Netcode; |
|
8 | 9 |
|
9 | 10 | namespace TestProject.RuntimeTests |
10 | 11 | { |
11 | | - public class DontDestroyOnLoadTests |
| 12 | + public class DontDestroyOnLoadTests : NetcodeIntegrationTest |
12 | 13 | { |
13 | | - private NetworkManager m_ServerNetworkManager; |
14 | | - private NetworkManager[] m_ClientNetworkManagers; |
15 | | - private GameObject m_PlayerPrefab; |
| 14 | + private const int k_ClientsToConnect = 4; |
| 15 | + protected override int NumberOfClients => 0; |
16 | 16 | private GameObject m_DontDestroyOnLoadObject; |
17 | 17 |
|
18 | | - |
19 | | - [UnitySetUp] |
20 | | - public IEnumerator Setup() |
| 18 | + protected override void OnServerAndClientsCreated() |
21 | 19 | { |
22 | | - // Create multiple NetworkManager instances |
23 | | - if (!NetcodeIntegrationTestHelpers.Create(4, out NetworkManager server, out NetworkManager[] clients, 60)) |
24 | | - { |
25 | | - Debug.LogError("Failed to create instances"); |
26 | | - Assert.Fail("Failed to create instances"); |
27 | | - } |
28 | | - |
29 | | - m_PlayerPrefab = new GameObject("Player"); |
30 | | - var playerNetworkObject = m_PlayerPrefab.AddComponent<NetworkObject>(); |
31 | | - |
32 | | - // Make it a prefab |
33 | | - NetcodeIntegrationTestHelpers.MakeNetworkObjectTestPrefab(playerNetworkObject); |
34 | | - |
35 | | - m_DontDestroyOnLoadObject = new GameObject("DontDestroyOnLoadObject"); |
36 | | - var dontDestroyOnLoadNetworkObject = m_DontDestroyOnLoadObject.AddComponent<NetworkObject>(); |
| 20 | + m_DontDestroyOnLoadObject = CreateNetworkObjectPrefab("DDOLObject"); |
37 | 21 | m_DontDestroyOnLoadObject.AddComponent<ObjectToNotDestroyBehaviour>(); |
38 | | - // Make it a prefab |
39 | | - NetcodeIntegrationTestHelpers.MakeNetworkObjectTestPrefab(dontDestroyOnLoadNetworkObject); |
40 | | - |
41 | | - // Set the player prefab |
42 | | - server.NetworkConfig.PlayerPrefab = m_PlayerPrefab; |
43 | | - // Add our test NetworkObject to be moved into the DontDestroyOnLoad scene |
44 | | - server.NetworkConfig.Prefabs.Add(new NetworkPrefab() { Override = NetworkPrefabOverride.None, Prefab = m_DontDestroyOnLoadObject }); |
45 | | - |
46 | | - // Apply the same settings for the clients |
47 | | - for (int i = 0; i < clients.Length; i++) |
48 | | - { |
49 | | - clients[i].NetworkConfig.PlayerPrefab = m_PlayerPrefab; |
50 | | - clients[i].NetworkConfig.Prefabs.Add(new NetworkPrefab() { Override = NetworkPrefabOverride.None, Prefab = m_DontDestroyOnLoadObject }); |
51 | | - } |
52 | | - |
53 | | - m_ServerNetworkManager = server; |
54 | | - m_ClientNetworkManagers = clients; |
55 | | - |
56 | | - yield return null; |
| 22 | + base.OnServerAndClientsCreated(); |
57 | 23 | } |
58 | 24 |
|
59 | | - [UnityTearDown] |
60 | | - public IEnumerator Teardown() |
| 25 | + protected override void OnNewClientCreated(NetworkManager networkManager) |
61 | 26 | { |
62 | | - NetcodeIntegrationTestHelpers.CleanUpHandlers(); |
63 | | - |
64 | | - m_ServerNetworkManager.Shutdown(); |
65 | | - foreach (var networkManager in m_ClientNetworkManagers) |
66 | | - { |
67 | | - networkManager.Shutdown(); |
68 | | - } |
69 | | - int nextFrameNumber = Time.frameCount + 4; |
70 | | - yield return new WaitUntil(() => Time.frameCount >= nextFrameNumber); |
71 | | - Object.Destroy(m_PlayerPrefab); |
72 | | - Object.Destroy(m_DontDestroyOnLoadObject); |
73 | | - Object.Destroy(m_ServerNetworkManager); |
74 | | - foreach (var networkManager in m_ClientNetworkManagers) |
75 | | - { |
76 | | - Object.Destroy(networkManager); |
77 | | - } |
78 | | - |
79 | | - m_ServerNetworkManager = null; |
80 | | - m_ClientNetworkManagers = null; |
| 27 | + networkManager.NetworkConfig.Prefabs = m_ServerNetworkManager.NetworkConfig.Prefabs; |
| 28 | + base.OnNewClientCreated(networkManager); |
| 29 | + } |
81 | 30 |
|
82 | | -#if UNITY_2023_1_OR_NEWER |
83 | | - var networkObjects = Object.FindObjectsByType<NetworkObject>(FindObjectsSortMode.InstanceID); |
84 | | -#else |
85 | | - var networkObjects = Object.FindObjectsOfType<NetworkObject>(); |
86 | | -#endif |
| 31 | + private ulong m_SpawnedNetworkObjectId; |
| 32 | + private StringBuilder m_ErrorLog = new StringBuilder(); |
87 | 33 |
|
88 | | - foreach (var netObject in networkObjects) |
| 34 | + private bool AllClientsSpawnedObjectIntoDDOL() |
| 35 | + { |
| 36 | + var passed = true; |
| 37 | + m_ErrorLog.Clear(); |
| 38 | + foreach (var client in m_ClientNetworkManagers) |
89 | 39 | { |
90 | | - Object.DestroyImmediate(netObject); |
| 40 | + if (!client.SpawnManager.SpawnedObjects.ContainsKey(m_SpawnedNetworkObjectId)) |
| 41 | + { |
| 42 | + m_ErrorLog.AppendLine($"[Client-{client.LocalClientId}] Has not spanwed NetworkObjectId: {m_SpawnedNetworkObjectId}!"); |
| 43 | + passed = false; |
| 44 | + continue; |
| 45 | + } |
| 46 | + |
| 47 | + var spawnedObject = client.SpawnManager.SpawnedObjects[m_SpawnedNetworkObjectId]; |
| 48 | + if (spawnedObject.NetworkManager == client && spawnedObject.gameObject.scene.name != "DontDestroyOnLoad") |
| 49 | + { |
| 50 | + m_ErrorLog.AppendLine($"[Client-{client.LocalClientId}] {spawnedObject.name} is not in DDOL scene but is in scene {spawnedObject.gameObject.scene.name}"); |
| 51 | + passed = false; |
| 52 | + continue; |
| 53 | + } |
91 | 54 | } |
92 | | - yield return null; |
| 55 | + return passed; |
93 | 56 | } |
94 | 57 |
|
95 | | - |
96 | 58 | [UnityTest] |
97 | 59 | public IEnumerator ValidateNetworkObjectSynchronization() |
98 | 60 | { |
99 | | - m_ServerNetworkManager.StartHost(); |
100 | | - NetcodeIntegrationTestHelpers.RegisterHandlers(m_ServerNetworkManager); |
101 | | - var objectInstance = Object.Instantiate(m_DontDestroyOnLoadObject); |
102 | | - var instanceNetworkObject = objectInstance.GetComponent<NetworkObject>(); |
103 | | - instanceNetworkObject.NetworkManagerOwner = m_ServerNetworkManager; |
104 | | - instanceNetworkObject.Spawn(); |
105 | | - var serverobjectToNotDestroyBehaviour = objectInstance.GetComponent<ObjectToNotDestroyBehaviour>(); |
106 | | - var waitForTick = new WaitForSeconds(1.0f / m_ServerNetworkManager.NetworkConfig.TickRate); |
107 | | - yield return waitForTick; |
| 61 | + var objectInstance = SpawnObject(m_DontDestroyOnLoadObject, m_ServerNetworkManager); |
| 62 | + m_SpawnedNetworkObjectId = objectInstance.GetComponent<NetworkObject>().NetworkObjectId; |
| 63 | + // Wait a tick for the object to be automatically migrated into the DDOL |
| 64 | + yield return s_DefaultWaitForTick; |
108 | 65 |
|
109 | 66 | Assert.IsTrue(objectInstance.scene.name == "DontDestroyOnLoad"); |
110 | 67 |
|
111 | | - foreach (var networkManager in m_ClientNetworkManagers) |
| 68 | + for (int i = 0; i < k_ClientsToConnect; i++) |
112 | 69 | { |
113 | | - networkManager.StartClient(); |
114 | | - NetcodeIntegrationTestHelpers.RegisterHandlers(networkManager); |
| 70 | + yield return CreateAndStartNewClient(); |
115 | 71 | } |
116 | 72 |
|
117 | | - yield return NetcodeIntegrationTestHelpers.WaitForClientsConnected(m_ClientNetworkManagers); |
118 | | - |
119 | | - yield return waitForTick; |
120 | | - var timeOut = Time.realtimeSinceStartup + 2.0f; |
121 | | - var timedOut = false; |
122 | | - while (!timedOut) |
123 | | - { |
124 | | - var allClientConditionsHaveBeenReached = true; |
125 | | - foreach (var networkManager in m_ClientNetworkManagers) |
126 | | - { |
127 | | - foreach (var spawnedObject in networkManager.SpawnManager.SpawnedObjectsList) |
128 | | - { |
129 | | - if (spawnedObject.NetworkManager == networkManager && spawnedObject.gameObject.name.Contains("DontDestroyOnLoadObject")) |
130 | | - { |
131 | | - if (spawnedObject.gameObject.scene.name != "DontDestroyOnLoad") |
132 | | - { |
133 | | - allClientConditionsHaveBeenReached = false; |
134 | | - break; |
135 | | - } |
136 | | - var objectToNotDestroyBehaviour = spawnedObject.gameObject.GetComponent<ObjectToNotDestroyBehaviour>(); |
137 | | - if (objectToNotDestroyBehaviour.CurrentPing == 0 || serverobjectToNotDestroyBehaviour.CurrentPing != objectToNotDestroyBehaviour.CurrentPing) |
138 | | - { |
139 | | - allClientConditionsHaveBeenReached = false; |
140 | | - break; |
141 | | - } |
142 | | - } |
143 | | - } |
144 | | - } |
145 | | - |
146 | | - if (allClientConditionsHaveBeenReached) |
147 | | - { |
148 | | - break; |
149 | | - } |
150 | | - |
151 | | - yield return waitForTick; |
152 | | - |
153 | | - timedOut = timeOut < Time.realtimeSinceStartup; |
154 | | - } |
155 | | - Assert.False(timedOut, "Timed out while waiting for all client conditions to be reached!"); |
| 73 | + yield return WaitForConditionOrTimeOut(AllClientsSpawnedObjectIntoDDOL); |
| 74 | + AssertOnTimeout($"[DDOL Test Failure] Reason for failure:\n {m_ErrorLog}"); |
156 | 75 | } |
157 | 76 | } |
158 | 77 | } |
0 commit comments