/// <summary> /// Internal method to handle scene loads /// </summary> private async Task LoadScenesInternal( IEnumerable <string> scenesToLoad, SceneType sceneType, SceneActivationToken activationToken = null, float progressOffset = 0, float progressTarget = 1, bool sceneOpInProgressWhenFinished = false) { // If we're using an activation token let it know that we're NOT ready to proceed activationToken?.SetReadyToProceed(false); SetSceneOpProgress(true, progressOffset, sceneType); // Validate our scenes List <string> validNames = new List <string>(); List <int> validIndexes = new List <int>(); foreach (string sceneName in scenesToLoad) { // See if scene exists Scene scene; int sceneIndex; if (!RuntimeSceneUtils.FindScene(sceneName, out scene, out sceneIndex)) { Debug.LogError("Can't load invalid scene " + sceneName); } else { validIndexes.Add(sceneIndex); validNames.Add(sceneName); } } int totalSceneOps = validIndexes.Count; if (totalSceneOps < 1) { Debug.LogWarning("No valid scenes found to load."); SetSceneOpProgress(sceneOpInProgressWhenFinished, progressTarget, sceneType); return; } // We're about to load scenes - let everyone know InvokeWillLoadActions(validNames, sceneType); // Load our scenes if (validIndexes.Count > 0) { List <AsyncOperation> loadSceneOps = new List <AsyncOperation>(); foreach (int sceneIndex in validIndexes) { Scene scene = SceneManager.GetSceneByBuildIndex(sceneIndex); if (scene.isLoaded) { continue; } AsyncOperation sceneOp = SceneManager.LoadSceneAsync(sceneIndex, LoadSceneMode.Additive); // Set this to true unless we have an activation token sceneOp.allowSceneActivation = (activationToken != null) ? activationToken.AllowSceneActivation : true; loadSceneOps.Add(sceneOp); } // Now wait for all async operations to complete bool completedAllSceneOps = false; while (!completedAllSceneOps) { if (!Application.isPlaying) { // Break out of this loop if we've stopped playmode return; } completedAllSceneOps = true; bool readyToProceed = false; bool allowSceneActivation = (activationToken != null) ? activationToken.AllowSceneActivation : true; // Go through all the load scene ops and see if we're ready to be activated float sceneOpProgress = 0; for (int i = 0; i < loadSceneOps.Count; i++) { // Set allow scene activation // (This can be set to true by user before ReadyToProceed is set) loadSceneOps[i].allowSceneActivation = allowSceneActivation; if (loadSceneOps[i].isDone) { // Sometimes if a scene is small enough, progress will get reset to 0 before you even have a chance to check it // This is true EVEN IF you've set allowSceneActivation to false // So use isDone as a failsafe sceneOpProgress += 1; } else { readyToProceed |= loadSceneOps[i].progress >= SceneActivationLoadProgress; sceneOpProgress += loadSceneOps[i].progress; completedAllSceneOps = false; } } // Let the activation know whether we're ready activationToken?.SetReadyToProceed(readyToProceed); sceneOpProgress = Mathf.Clamp01(SceneOperationProgress / totalSceneOps); SetSceneOpProgress(true, Mathf.Lerp(progressOffset, progressTarget, sceneOpProgress), sceneType); await Task.Yield(); } } // Wait for all scenes to be fully loaded before proceeding bool scenesLoadedAndActivated = false; while (!scenesLoadedAndActivated) { if (!Application.isPlaying) { // Break out of this loop if we've stopped playmode return; } scenesLoadedAndActivated = true; foreach (int sceneIndex in validIndexes) { Scene scene = SceneManager.GetSceneByBuildIndex(sceneIndex); scenesLoadedAndActivated &= (scene.IsValid() & scene.isLoaded); } await Task.Yield(); } // Make sure our content tracker is refreshed contentTracker.RefreshLoadedContent(); // We're done! SetSceneOpProgress(sceneOpInProgressWhenFinished, progressTarget, sceneType); InvokeLoadedActions(validNames, sceneType); }
/// <inheritdoc /> public async Task LoadContent(IEnumerable <string> scenesToLoad, LoadSceneMode mode = LoadSceneMode.Additive, SceneActivationToken activationToken = null) { if (!CanSceneOpProceed(SceneType.Content)) { Debug.LogError("Attempting to perform a scene op when a scene op is already in progress."); return; } IEnumerable <string> loadedContentScenes; if (mode == LoadSceneMode.Single && GetLoadedContentScenes(out loadedContentScenes)) { await UnloadScenesInternal(loadedContentScenes, SceneType.Content, 0, 0.5f, true); await LoadScenesInternal(scenesToLoad, SceneType.Content, activationToken, 0.5f, 1f, false); } else { await LoadScenesInternal(scenesToLoad, SceneType.Content, activationToken); } await LoadScenesInternal(scenesToLoad, SceneType.Content, activationToken); }
/// <inheritdoc /> public async Task LoadContent(string sceneToLoad, LoadSceneMode mode = LoadSceneMode.Additive, SceneActivationToken activationToken = null) { await LoadContent(new string[] { sceneToLoad }, mode, activationToken); }
/// <inheritdoc /> public async Task LoadContentByTag(string tag, LoadSceneMode mode = LoadSceneMode.Additive, SceneActivationToken activationToken = null) { await LoadContent(profile.GetContentSceneNamesByTag(tag), mode, activationToken); }
/// <inheritdoc /> public async Task LoadPrevContent(bool wrap = false, LoadSceneMode mode = LoadSceneMode.Single, SceneActivationToken activationToken = null) { string prevContent; if (contentTracker.GetPrevContent(wrap, out prevContent)) { await LoadContent(new string[] { prevContent }, mode, activationToken); } else { Debug.LogWarning("Attempted to load prev content when no next content exists. Taking no action."); } }