using System.Collections; using NUnit.Framework; using Unity.Netcode.TestHelpers.Runtime; using UnityEngine; using UnityEngine.TestTools; namespace Unity.Netcode.RuntimeTests { /// /// Tests that check OnNetworkDespawn being invoked /// [TestFixture(HostOrServer.Host)] [TestFixture(HostOrServer.Server)] public class NetworkObjectOnNetworkDespawnTests : NetcodeIntegrationTest { private const string k_ObjectName = "TestDespawn"; public enum InstanceType { Server, Client } protected override int NumberOfClients => 1; private GameObject m_ObjectToSpawn; private HostOrServer m_HostOrServer; public NetworkObjectOnNetworkDespawnTests(HostOrServer hostOrServer) : base(hostOrServer) { m_HostOrServer = hostOrServer; } internal class OnNetworkDespawnTestComponent : NetworkBehaviour { public static bool OnServerNetworkDespawnCalled { get; internal set; } public static bool OnClientNetworkDespawnCalled { get; internal set; } public override void OnNetworkSpawn() { if (IsServer) { OnServerNetworkDespawnCalled = false; } else { OnClientNetworkDespawnCalled = false; } base.OnNetworkSpawn(); } public override void OnNetworkDespawn() { if (IsServer) { OnServerNetworkDespawnCalled = true; } else { OnClientNetworkDespawnCalled = true; } base.OnNetworkDespawn(); } } protected override void OnServerAndClientsCreated() { m_ObjectToSpawn = CreateNetworkObjectPrefab(k_ObjectName); m_ObjectToSpawn.AddComponent(); base.OnServerAndClientsCreated(); } /// /// This test validates that is invoked when the /// is shutdown. /// [UnityTest] public IEnumerator TestNetworkObjectDespawnOnShutdown() { // Spawn the test object var spawnedObject = SpawnObject(m_ObjectToSpawn, m_ServerNetworkManager); var spawnedNetworkObject = spawnedObject.GetComponent(); // Wait for the client to spawn the object yield return WaitForConditionOrTimeOut(() => { if (!s_GlobalNetworkObjects.ContainsKey(m_ClientNetworkManagers[0].LocalClientId)) { return false; } if (!s_GlobalNetworkObjects[m_ClientNetworkManagers[0].LocalClientId].ContainsKey(spawnedNetworkObject.NetworkObjectId)) { return false; } return true; }); AssertOnTimeout($"Timed out waiting for client to spawn {k_ObjectName}!"); // Confirm it is not set before shutting down the NetworkManager Assert.IsFalse(OnNetworkDespawnTestComponent.OnClientNetworkDespawnCalled, "[Client-side] despawn state is already set (should not be set at this point)!"); Assert.IsFalse(OnNetworkDespawnTestComponent.OnServerNetworkDespawnCalled, $"[{m_HostOrServer}-side] despawn state is already set (should not be set at this point)!"); // Shutdown the client-side first to validate the client-side instance invokes OnNetworkDespawn m_ClientNetworkManagers[0].Shutdown(); yield return WaitForConditionOrTimeOut(() => OnNetworkDespawnTestComponent.OnClientNetworkDespawnCalled); AssertOnTimeout($"[Client-side] Timed out waiting for {k_ObjectName}'s {nameof(NetworkBehaviour.OnNetworkDespawn)} to be invoked!"); // Shutdown the servr-host-side second to validate servr-host-side instance invokes OnNetworkDespawn m_ServerNetworkManager.Shutdown(); yield return WaitForConditionOrTimeOut(() => OnNetworkDespawnTestComponent.OnClientNetworkDespawnCalled); AssertOnTimeout($"[{m_HostOrServer}-side]Timed out waiting for {k_ObjectName}'s {nameof(NetworkBehaviour.OnNetworkDespawn)} to be invoked!"); } } }