using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using UnityEngine; using UnityEngine.SceneManagement; using UnityUtils; namespace MyCollections.SceneManagement { public class SceneGroupManager { public event Action<string> OnSceneLoaded = delegate { }; public event Action<string> OnSceneUnloaded = delegate { }; public event Action OnSceneGroupLoaded = delegate { }; private SceneGroup activeSceneGroup; public async Task LoadScenes(SceneGroup group, bool reloadDupScenes = false) { activeSceneGroup = group; List<string> loadedScenes = new List<string>(); int sceneCount = SceneManager.sceneCount; Debug.Log("Get Scenes: " + sceneCount); for (int i = 0; i < sceneCount; i++) { Debug.Log("Get Scenes: " + SceneManager.GetSceneAt(i).name); loadedScenes.Add(SceneManager.GetSceneAt(i).name); } int totalScenesToLoad = activeSceneGroup.scenes.Count; AsyncOperationGroup operationGroup = new AsyncOperationGroup(totalScenesToLoad); for (int i = 0; i < totalScenesToLoad; i++) { SceneData sceneData = group.scenes[i]; if (reloadDupScenes == false && loadedScenes.Contains(sceneData.Name)) continue; AsyncOperation operation = SceneManager.LoadSceneAsync(sceneData.reference.Path, LoadSceneMode.Additive); await Task.Delay(TimeSpan.FromSeconds(2.5f)); //Testing purposes operationGroup.operations.Add(operation); OnSceneLoaded.Invoke(sceneData.Name); } //Wait until AsyncOperatons in the group are done while (!operationGroup.isDone) { //progress?.Report(operationGroup.Progress); Debug.Log("Waiting operation"); await Task.Delay(100); } await Task.Delay(100); Scene activeScene = SceneManager.GetSceneByName(activeSceneGroup.FindSceneNameByType(SceneType.ActiveScene)); if (activeScene.IsValid()) SceneManager.SetActiveScene(activeScene); await UnloadScenes(); OnSceneGroupLoaded.Invoke(); } //Unload scenes public async Task UnloadScenes() { //Creates a list for the scene names List<string> scenes = new List<string>(); //Get's the current scene name string activeScene = SceneManager.GetActiveScene().name; Debug.Log($"Active scene name: {activeScene}"); //Counts the number of scenes int sceneCount = SceneManager.sceneCount; Debug.Log($"Number of scenes: {sceneCount}"); //Loop reversely for (int i = sceneCount - 1; i >= 0; i--) { //Gets the scene by index Scene sceneAt = SceneManager.GetSceneAt(i); Debug.Log($"Checking scene: {sceneAt.name}"); //Checks if it's not loaded, continues if(!sceneAt.isLoaded) continue; //gets the name of the current index scene string sceneName = sceneAt.name; //Checks if the index scene name is equal to the active scene if (sceneName.Equals(activeScene)) continue; //Add's the scene to the list scenes.Add(sceneName); Debug.Log($"Added scene: {sceneName}"); } //Create an AsyncOperationGroup AsyncOperationGroup operationGroup = new AsyncOperationGroup(sceneCount); //foreach through the list foreach (string scene in scenes) { Debug.Log($"Unload Scene: {scene}"); //Stores the operation AsyncOperation operation = SceneManager.UnloadSceneAsync(scene); if (operation == null) continue; //Adds the operation to the list of operations operationGroup.operations.Add(operation); Debug.Log($"Added operation: {operation}"); foreach (AsyncOperation op in operationGroup.operations) { Debug.Log($"Operation: {op}"); } //invoke a message OnSceneUnloaded.Invoke(scene); } Debug.Log($"Operations count: {operationGroup.operations.Count}"); //Wait until AsyncOperatons in the group are done while (!operationGroup.isDone) { Debug.Log("Operation is not Done!"); await Task.Delay(100); //Delay to avoid tight loop } //Optional: UnloadUnusedAssets - Unloads all unused assets from memory //Expensive operation await AsyncOperationExtensions.AsTask(Resources.UnloadUnusedAssets()); } } public readonly struct AsyncOperationGroup { public readonly List<AsyncOperation> operations; public float Progress => operations.Count == 0 ? 0 : operations.Average(o => o.progress); public bool isDone => operations.All(o => o.isDone); public AsyncOperationGroup(int initialCapacity) => operations = new List<AsyncOperation>(initialCapacity); } }