private static IEnumerator InternalDeInitialize(Action onDone) { var sw = Stopwatch.StartNew(); // the initialize client OnUnloadClientSideContent?.Invoke(); // activate loading screen OnClientLoadingInfoUpdated?.Invoke(true, "UNLOADING WORLD", "Destroying players."); OnClientLoadingStart?.Invoke(); LastMapState = QNetMapState.Unloading; OnMapStateChanged?.Invoke(LastMapState); // destroy players yield return(QNetPlayer.DestroyAllQNetPlayers()); // activate loading screen OnClientLoadingInfoUpdated?.Invoke(true, "UNLOADING WORLD", $"Destroying {QNetWorldSerializer.SerializedAndInstancedObjects.Count} objects."); // destroy world objects var isDestroyingWorldObjects = true; QNetWorldSerializer.DestroySerializedObjects(() => { isDestroyingWorldObjects = false; }); while (isDestroyingWorldObjects) { yield return(new WaitForEndOfFrame()); } // try to destroy rest of QNet objects just for sure if (QNetObjectBehaviour.SpawnedBehaviours.Length != 0) { JEMLogger.Log( $"QNetUnity find and will destroy {QNetObjectBehaviour.SpawnedBehaviours.Length} additional objects that has been created not by QNetWorldSerializer."); } while (QNetObjectBehaviour.SpawnedBehaviours.Length > 0) { QNetObjectBehaviour.InternalDestroy(QNetObjectBehaviour.SpawnedBehaviours[0]); yield return(new WaitForEndOfFrame()); } // activate loading screen OnClientLoadingInfoUpdated?.Invoke(true, "UNLOADING LEVEL", "Unloading level."); // unload world var isLevelUnLoading = true; QNetLevelLoader.UnLoad(() => { isLevelUnLoading = false; }); while (isLevelUnLoading) { yield return(new WaitForEndOfFrame()); } // clear behaviours just for sure QNetObjectBehaviour.ClearBehaviours(); LastMapState = QNetMapState.NotLoaded; OnMapStateChanged?.Invoke(LastMapState); GameIsDeInitializing = false; GameInitialized = false; OnClientLoadingEnd?.Invoke(); JEMLogger.Log($"QNetUnity DeInitialization main work took {sw.Elapsed.Milliseconds:0.00}ms."); onDone?.Invoke(); }