From 872ee5860bbeb4fbcc416925718c9dcc87d8e908 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Borks?= Date: Tue, 27 Aug 2024 19:07:54 -0300 Subject: [PATCH] feat: add new scene transition methods (#46) * update scene loader interface * add new transitions to scene loaders * add transitiontoscenesfromscenes test * add transitiontoscenesfromall test * add documentation for new transition methods --- Runtime/Interfaces/ISceneLoader.cs | 103 ++++++++++++++++++- Runtime/Interfaces/ISceneLoaderAsync.cs | 72 +++++++++++++ Runtime/SceneLoaders/SceneLoaderAsync.cs | 89 +++++++++++++--- Runtime/SceneLoaders/SceneLoaderCoroutine.cs | 40 +++++++ Runtime/SceneLoaders/SceneLoaderUniTask.cs | 40 +++++++ Tests/Runtime/SceneLoaderTests.cs | 92 +++++++++++++++++ 6 files changed, 419 insertions(+), 17 deletions(-) diff --git a/Runtime/Interfaces/ISceneLoader.cs b/Runtime/Interfaces/ISceneLoader.cs index 66d242a..140b82c 100644 --- a/Runtime/Interfaces/ISceneLoader.cs +++ b/Runtime/Interfaces/ISceneLoader.cs @@ -15,7 +15,7 @@ public interface ISceneLoader : IDisposable ISceneManager Manager { get; } /// - /// Triggers a transition to a group of scens. + /// Triggers a transition to a group of scenes from the active scene. /// It will transition from the current active scene () /// to a group of scenes (), with an optional intermediate loading scene (). /// If the is not set, the transition will have no intermediate loading scene and will instead simply load the target scene directly. @@ -39,7 +39,7 @@ public interface ISceneLoader : IDisposable void TransitionToScenes(ILoadSceneInfo[] targetScenes, int setIndexActive, ILoadSceneInfo intermediateSceneInfo = null); /// - /// Triggers a scene transition. + /// Triggers a transition to the target scene from the active scene. /// It will transition from the current active scene () /// to the target scene (), with an optional intermediate loading scene (). /// If the is not set, the transition will have no intermediate loading scene and will instead simply load the target scene directly. @@ -59,6 +59,105 @@ public interface ISceneLoader : IDisposable /// void TransitionToScene(ILoadSceneInfo targetSceneInfo, ILoadSceneInfo intermediateSceneInfo = null); + /// + /// Triggers a transition to a group of scenes from another group of scenes. + /// It will transition from the provided group of scenes () + /// to a group of scenes (), with an optional intermediate loading scene (). + /// If the is not set, the transition will have no intermediate loading scene and will instead simply load the target scene directly. + /// The complete transition flow is: + ///

+ /// 1. Load the intermediate scene (if provided).
+ /// 2. Unload all provided scenes.
+ /// 3. Load all target scenes.
+ /// 4. Unload the intermediate scene (if provided).
+ ///
+ /// + /// A reference to all scenes that will be transitioned to. + /// + /// + /// A reference to all scenes that will be unloaded in the transition. + /// + /// + /// Index of the scene in the to be set as the active scene. + /// + /// + /// A reference to the scene that's going to be loaded as the transition intermediate (as a loading scene). + /// If null, the transition will not have an intermediate loading scene. + /// + void TransitionToScenesFromScenes(ILoadSceneInfo[] targetScenes, ILoadSceneInfo[] fromScenes, int setIndexActive, ILoadSceneInfo intermediateSceneInfo = null); + + /// + /// Triggers a transition to the target scene from a group of scens. + /// It will transition from the provided group of scenes () + /// to the target scene (), with an optional intermediate loading scene (). + /// If the is not set, the transition will have no intermediate loading scene and will instead simply load the target scene directly. + /// The complete transition flow is: + ///

+ /// 1. Load the intermediate scene (if provided).
+ /// 2. Unload all provided scenes.
+ /// 3. Load the target scene.
+ /// 4. Unload the intermediate scene (if provided).
+ ///
+ /// + /// A reference to the scene that's going to be transitioned to. + /// + /// + /// A reference to all scenes that will be unloaded in the transition. + /// + /// + /// A reference to the scene that's going to be loaded as the transition intermediate (as a loading scene). + /// If null, the transition will not have an intermediate loading scene. + /// + void TransitionToSceneFromScenes(ILoadSceneInfo targetSceneInfo, ILoadSceneInfo[] fromScenes, ILoadSceneInfo intermediateSceneInfo = null); + + /// + /// Triggers a transition to a group of scenes from all loaded scenes. + /// It will transition from all loaded scenes + /// to a group of scenes (), with an optional intermediate loading scene (). + /// If the is not set, the transition will have no intermediate loading scene and will instead simply load the target scene directly. + /// The complete transition flow is: + ///

+ /// 1. Load the intermediate scene (if provided).
+ /// 2. Unload all loaded scenes.
+ /// 3. Load all target scenes.
+ /// 4. Unload the intermediate scene (if provided).
+ ///
+ /// + /// A reference to all scenes that will be transitioned to. + /// + /// + /// Index of the scene in the to be set as the active scene. + /// + /// + /// A reference to the scene that's going to be loaded as the transition intermediate (as a loading scene). + /// If null, the transition will not have an intermediate loading scene. + /// + void TransitionToScenesFromAll(ILoadSceneInfo[] targetScenes, int setIndexActive, ILoadSceneInfo intermediateSceneInfo = null); + + /// + /// Triggers a transition to the target scene from all loaded scenes. + /// It will transition from the provided group of scenes () + /// to the target scene (), with an optional intermediate loading scene (). + /// If the is not set, the transition will have no intermediate loading scene and will instead simply load the target scene directly. + /// The complete transition flow is: + ///

+ /// 1. Load the intermediate scene (if provided).
+ /// 2. Unload all provided scenes.
+ /// 3. Load the target scene.
+ /// 4. Unload the intermediate scene (if provided).
+ ///
+ /// + /// A reference to the scene that's going to be transitioned to. + /// + /// + /// A reference to all scenes that will be unloaded in the transition. + /// + /// + /// A reference to the scene that's going to be loaded as the transition intermediate (as a loading scene). + /// If null, the transition will not have an intermediate loading scene. + /// + void TransitionToSceneFromAll(ILoadSceneInfo targetSceneInfo, ILoadSceneInfo intermediateSceneInfo = null); + /// /// Unloads all the scenes from the current scene stack. /// diff --git a/Runtime/Interfaces/ISceneLoaderAsync.cs b/Runtime/Interfaces/ISceneLoaderAsync.cs index d93495c..bab84fc 100644 --- a/Runtime/Interfaces/ISceneLoaderAsync.cs +++ b/Runtime/Interfaces/ISceneLoaderAsync.cs @@ -49,6 +49,78 @@ public interface ISceneLoaderAsync : ISceneLoader /// TAsyncScene TransitionToSceneAsync(ILoadSceneInfo targetSceneReference, ILoadSceneInfo intermediateSceneReference = default); + /// + /// Async version of the + /// + /// + /// A reference to all scenes that will be transitioned to. + /// + /// + /// A reference to all scenes that will be unloaded in the transition. + /// + /// + /// Index of the scene in the to be set as the active scene. + /// + /// + /// A reference to the scene that's going to be loaded as the transition intermediate (as a loading scene). + /// If null, the transition will not have an intermediate loading scene. + /// + /// + /// The transition operation. + /// + TAsyncSceneArray TransitionToScenesFromScenesAsync(ILoadSceneInfo[] targetScenes, ILoadSceneInfo[] fromScenes, int setIndexActive, ILoadSceneInfo intermediateSceneReference = default); + + /// + /// Async version of the + /// + /// + /// A reference to the scene that's going to be transitioned to. + /// + /// + /// A reference to all scenes that will be unloaded in the transition. + /// + /// + /// A reference to the scene that's going to be loaded as the transition intermediate (as a loading scene). + /// If null, the transition will not have an intermediate loading scene. + /// + /// + /// The transition operation. + /// + TAsyncScene TransitionToSceneFromScenesAsync(ILoadSceneInfo targetSceneReference, ILoadSceneInfo[] fromScenes, ILoadSceneInfo intermediateSceneReference = default); + + /// + /// Async version of the + /// + /// + /// A reference to all scenes that will be transitioned to. + /// + /// + /// Index of the scene in the to be set as the active scene. + /// + /// + /// A reference to the scene that's going to be loaded as the transition intermediate (as a loading scene). + /// If null, the transition will not have an intermediate loading scene. + /// + /// + /// The transition operation. + /// + TAsyncSceneArray TransitionToScenesFromAllAsync(ILoadSceneInfo[] targetScenes, int setIndexActive, ILoadSceneInfo intermediateSceneReference = default); + + /// + /// Async version of the + /// + /// + /// A reference to the scene that's going to be transitioned to. + /// + /// + /// A reference to the scene that's going to be loaded as the transition intermediate (as a loading scene). + /// If null, the transition will not have an intermediate loading scene. + /// + /// + /// The transition operation. + /// + TAsyncScene TransitionToSceneFromAllAsync(ILoadSceneInfo targetSceneReference, ILoadSceneInfo intermediateSceneReference = default); + /// /// Async version of the . /// diff --git a/Runtime/SceneLoaders/SceneLoaderAsync.cs b/Runtime/SceneLoaders/SceneLoaderAsync.cs index 3398991..eed0012 100644 --- a/Runtime/SceneLoaders/SceneLoaderAsync.cs +++ b/Runtime/SceneLoaders/SceneLoaderAsync.cs @@ -37,6 +37,26 @@ public void TransitionToScene(ILoadSceneInfo targetSceneInfo, ILoadSceneInfo int TransitionToSceneAsync(targetSceneInfo, intermediateSceneInfo).AsTask().Forget(HandleFireAndForgetException); } + public void TransitionToScenesFromScenes(ILoadSceneInfo[] targetScenes, ILoadSceneInfo[] fromScenes, int setIndexActive, ILoadSceneInfo intermediateSceneInfo = null) + { + TransitionToScenesFromScenesAsync(targetScenes, fromScenes, setIndexActive, intermediateSceneInfo).Forget(HandleFireAndForgetException); + } + + public void TransitionToSceneFromScenes(ILoadSceneInfo targetSceneInfo, ILoadSceneInfo[] fromScenes, ILoadSceneInfo intermediateSceneInfo = null) + { + TransitionToSceneFromScenesAsync(targetSceneInfo, fromScenes, intermediateSceneInfo).Forget(HandleFireAndForgetException); + } + + public void TransitionToScenesFromAll(ILoadSceneInfo[] targetScenes, int setIndexActive, ILoadSceneInfo intermediateSceneInfo = null) + { + TransitionToScenesFromAllAsync(targetScenes, setIndexActive, intermediateSceneInfo).Forget(HandleFireAndForgetException); + } + + public void TransitionToSceneFromAll(ILoadSceneInfo targetSceneInfo, ILoadSceneInfo intermediateSceneInfo = null) + { + TransitionToSceneFromAllAsync(targetSceneInfo, intermediateSceneInfo).Forget(HandleFireAndForgetException); + } + public void UnloadScenes(ILoadSceneInfo[] sceneInfos) { UnloadScenesAsync(sceneInfos).AsTask().Forget(HandleFireAndForgetException); @@ -59,9 +79,11 @@ public void LoadScene(ILoadSceneInfo sceneInfo, bool setActive = false) public ValueTask TransitionToScenesAsync(ILoadSceneInfo[] targetScenes, int setIndexActive, ILoadSceneInfo intermediateSceneReference = null) { + Scene activeScene = _manager.GetActiveScene(); + ILoadSceneInfo[] fromScenes = activeScene.IsValid() ? new ILoadSceneInfo[] { new LoadSceneInfoScene(activeScene) } : null; return intermediateSceneReference == null - ? TransitionDirectlyAsync(targetScenes, setIndexActive, _lifetimeTokenSource.Token) - : TransitionWithIntermediateAsync(targetScenes, setIndexActive, intermediateSceneReference, _lifetimeTokenSource.Token); + ? TransitionDirectlyAsync(targetScenes, fromScenes, setIndexActive, _lifetimeTokenSource.Token) + : TransitionWithIntermediateAsync(targetScenes, fromScenes, setIndexActive, intermediateSceneReference, _lifetimeTokenSource.Token); } public async ValueTask TransitionToSceneAsync(ILoadSceneInfo targetSceneInfo, ILoadSceneInfo intermediateSceneInfo = default) @@ -70,6 +92,33 @@ public async ValueTask TransitionToSceneAsync(ILoadSceneInfo targetSceneI return result == null || result.Length == 0 ? default : result[0]; } + public ValueTask TransitionToScenesFromScenesAsync(ILoadSceneInfo[] targetScenes, ILoadSceneInfo[] fromScenes, int setIndexActive, ILoadSceneInfo intermediateSceneReference = null) + { + return intermediateSceneReference == null + ? TransitionDirectlyAsync(targetScenes, fromScenes, setIndexActive, _lifetimeTokenSource.Token) + : TransitionWithIntermediateAsync(targetScenes, fromScenes, setIndexActive, intermediateSceneReference, _lifetimeTokenSource.Token); + } + + public async ValueTask TransitionToSceneFromScenesAsync(ILoadSceneInfo targetSceneInfo, ILoadSceneInfo[] fromScenes, ILoadSceneInfo intermediateSceneReference = null) + { + var result = await TransitionToScenesFromScenesAsync(new ILoadSceneInfo[] { targetSceneInfo }, fromScenes, 0, intermediateSceneReference); + return result == null || result.Length == 0 ? default : result[0]; + } + + public ValueTask TransitionToScenesFromAllAsync(ILoadSceneInfo[] targetScenes, int setIndexActive, ILoadSceneInfo intermediateSceneReference = null) + { + ILoadSceneInfo[] fromScenes = GetAllLoadedSceneInfos(); + return intermediateSceneReference == null + ? TransitionDirectlyAsync(targetScenes, fromScenes, setIndexActive, _lifetimeTokenSource.Token) + : TransitionWithIntermediateAsync(targetScenes, fromScenes, setIndexActive, intermediateSceneReference, _lifetimeTokenSource.Token); + } + + public async ValueTask TransitionToSceneFromAllAsync(ILoadSceneInfo targetSceneInfo, ILoadSceneInfo intermediateSceneReference = null) + { + var result = await TransitionToScenesFromAllAsync(new ILoadSceneInfo[] { targetSceneInfo }, 0, intermediateSceneReference); + return result == null || result.Length == 0 ? default : result[0]; + } + public ValueTask LoadScenesAsync(ILoadSceneInfo[] sceneReferences, int setIndexActive = -1, IProgress progress = null) { return _manager.LoadScenesAsync(sceneReferences, setIndexActive, progress, _lifetimeTokenSource.Token); @@ -90,7 +139,7 @@ public ValueTask UnloadSceneAsync(ILoadSceneInfo sceneInfo) return _manager.UnloadSceneAsync(sceneInfo, _lifetimeTokenSource.Token); } - async ValueTask TransitionDirectlyAsync(ILoadSceneInfo[] targetScenes, int setIndexActive, CancellationToken token) + async ValueTask TransitionDirectlyAsync(ILoadSceneInfo[] targetScenes, ILoadSceneInfo[] fromScenes, int setIndexActive, CancellationToken token) { // If only one scene is loaded, we need to create a temporary scene for transition. Scene tempScene = default; @@ -98,7 +147,7 @@ async ValueTask TransitionDirectlyAsync(ILoadSceneInfo[] targetScenes, { tempScene = SceneManager.CreateScene("temp-transition-scene"); } - await UnloadSourceSceneAsync(token); + await UnloadSourceScenesAsync(fromScenes, token); Scene[] loadedScenes = await _manager.LoadScenesAsync(targetScenes, setIndexActive, token: token); @@ -109,7 +158,7 @@ async ValueTask TransitionDirectlyAsync(ILoadSceneInfo[] targetScenes, return loadedScenes; } - async ValueTask TransitionWithIntermediateAsync(ILoadSceneInfo[] targetScenes, int setIndexActive, ILoadSceneInfo intermediateSceneInfo, CancellationToken token) + async ValueTask TransitionWithIntermediateAsync(ILoadSceneInfo[] targetScenes, ILoadSceneInfo[] fromScenes, int setIndexActive, ILoadSceneInfo intermediateSceneInfo, CancellationToken token) { Scene loadingScene; try @@ -129,11 +178,11 @@ async ValueTask TransitionWithIntermediateAsync(ILoadSceneInfo[] target LoadingBehavior loadingBehavior = UnityEngine.Object.FindObjectsOfType().FirstOrDefault(l => l.gameObject.scene == loadingScene); #endif return loadingBehavior - ? await TransitionWithIntermediateLoadingAsync(targetScenes, setIndexActive, intermediateSceneInfo, loadingBehavior, token) - : await TransitionWithIntermediateNoLoadingAsync(targetScenes, setIndexActive, intermediateSceneInfo, token); + ? await TransitionWithIntermediateLoadingAsync(targetScenes, fromScenes, setIndexActive, intermediateSceneInfo, loadingBehavior, token) + : await TransitionWithIntermediateNoLoadingAsync(targetScenes, fromScenes, setIndexActive, intermediateSceneInfo, token); } - async ValueTask TransitionWithIntermediateLoadingAsync(ILoadSceneInfo[] targetScenes, int setIndexActive, ILoadSceneInfo intermediateSceneInfo, LoadingBehavior loadingBehavior, CancellationToken token) + async ValueTask TransitionWithIntermediateLoadingAsync(ILoadSceneInfo[] targetScenes, ILoadSceneInfo[] fromScenes, int setIndexActive, ILoadSceneInfo intermediateSceneInfo, LoadingBehavior loadingBehavior, CancellationToken token) { LoadingProgress progress = loadingBehavior.Progress; while (progress.State != LoadingState.Loading && !token.IsCancellationRequested) @@ -141,7 +190,7 @@ async ValueTask TransitionWithIntermediateLoadingAsync(ILoadSceneInfo[] token.ThrowIfCancellationRequested(); - await UnloadSourceSceneAsync(token); + await UnloadSourceScenesAsync(fromScenes, token); Scene[] loadedScenes = await _manager.LoadScenesAsync(targetScenes, setIndexActive, progress, token); progress.SetState(LoadingState.TargetSceneLoaded); @@ -155,21 +204,31 @@ async ValueTask TransitionWithIntermediateLoadingAsync(ILoadSceneInfo[] return loadedScenes; } - async ValueTask TransitionWithIntermediateNoLoadingAsync(ILoadSceneInfo[] targetScenes, int setIndexActive, ILoadSceneInfo intermediateSceneInfo, CancellationToken token) + async ValueTask TransitionWithIntermediateNoLoadingAsync(ILoadSceneInfo[] targetScenes, ILoadSceneInfo[] fromScenes, int setIndexActive, ILoadSceneInfo intermediateSceneInfo, CancellationToken token) { - await UnloadSourceSceneAsync(token); + await UnloadSourceScenesAsync(fromScenes, token); Scene[] loadedScenes = await _manager.LoadScenesAsync(targetScenes, setIndexActive, token: token); _manager.UnloadSceneAsync(intermediateSceneInfo, token).Forget(HandleFireAndForgetException); return loadedScenes; } - ValueTask UnloadSourceSceneAsync(CancellationToken token) + ValueTask UnloadSourceScenesAsync(ILoadSceneInfo[] fromScenes, CancellationToken token) { - Scene sourceScene = _manager.GetActiveScene(); - if (!sourceScene.IsValid()) + if (fromScenes == null || fromScenes.Length == 0) return default; - return _manager.UnloadSceneAsync(new LoadSceneInfoScene(sourceScene), token); + return _manager.UnloadScenesAsync(fromScenes, token); + } + + ILoadSceneInfo[] GetAllLoadedSceneInfos() + { + int count = _manager.LoadedSceneCount; + ILoadSceneInfo[] loadedSceneInfos = new ILoadSceneInfo[count]; + for (int i = 0; i < count; i++) + { + loadedSceneInfos[i] = new LoadSceneInfoScene(_manager.GetLoadedSceneAt(i)); + } + return loadedSceneInfos; } void HandleFireAndForgetException(Exception exception) diff --git a/Runtime/SceneLoaders/SceneLoaderCoroutine.cs b/Runtime/SceneLoaders/SceneLoaderCoroutine.cs index bd347ca..11d5afb 100644 --- a/Runtime/SceneLoaders/SceneLoaderCoroutine.cs +++ b/Runtime/SceneLoaders/SceneLoaderCoroutine.cs @@ -33,6 +33,26 @@ public void TransitionToScene(ILoadSceneInfo targetSceneInfo, ILoadSceneInfo int TransitionToSceneAsync(targetSceneInfo, intermediateSceneInfo); } + public void TransitionToScenesFromScenes(ILoadSceneInfo[] targetScenes, ILoadSceneInfo[] fromScenes, int setIndexActive, ILoadSceneInfo intermediateSceneInfo = null) + { + TransitionToScenesFromScenesAsync(targetScenes, fromScenes, setIndexActive, intermediateSceneInfo); + } + + public void TransitionToSceneFromScenes(ILoadSceneInfo targetSceneInfo, ILoadSceneInfo[] fromScenes, ILoadSceneInfo intermediateSceneInfo = null) + { + TransitionToSceneFromScenesAsync(targetSceneInfo, fromScenes, intermediateSceneInfo); + } + + public void TransitionToScenesFromAll(ILoadSceneInfo[] targetScenes, int setIndexActive, ILoadSceneInfo intermediateSceneInfo = null) + { + TransitionToScenesFromAllAsync(targetScenes, setIndexActive, intermediateSceneInfo); + } + + public void TransitionToSceneFromAll(ILoadSceneInfo targetSceneInfo, ILoadSceneInfo intermediateSceneInfo = null) + { + TransitionToSceneFromAllAsync(targetSceneInfo, intermediateSceneInfo); + } + public void UnloadScenes(ILoadSceneInfo[] sceneInfos) { UnloadScenesAsync(sceneInfos); @@ -63,6 +83,26 @@ public WaitTask TransitionToSceneAsync(ILoadSceneInfo targetSceneReferenc return new WaitTask(_sceneLoaderAsync.TransitionToSceneAsync(targetSceneReference, intermediateSceneReference).AsTask()); } + public WaitTask TransitionToScenesFromScenesAsync(ILoadSceneInfo[] targetScenes, ILoadSceneInfo[] fromScenes, int setIndexActive, ILoadSceneInfo intermediateSceneReference = null) + { + return new WaitTask(_sceneLoaderAsync.TransitionToScenesFromScenesAsync(targetScenes, fromScenes, setIndexActive, intermediateSceneReference).AsTask()); + } + + public WaitTask TransitionToSceneFromScenesAsync(ILoadSceneInfo targetSceneReference, ILoadSceneInfo[] fromScenes, ILoadSceneInfo intermediateSceneReference = null) + { + return new WaitTask(_sceneLoaderAsync.TransitionToSceneFromScenesAsync(targetSceneReference, fromScenes, intermediateSceneReference).AsTask()); + } + + public WaitTask TransitionToScenesFromAllAsync(ILoadSceneInfo[] targetScenes, int setIndexActive, ILoadSceneInfo intermediateSceneReference = null) + { + return new WaitTask(_sceneLoaderAsync.TransitionToScenesFromAllAsync(targetScenes, setIndexActive, intermediateSceneReference).AsTask()); + } + + public WaitTask TransitionToSceneFromAllAsync(ILoadSceneInfo targetSceneReference, ILoadSceneInfo intermediateSceneReference = null) + { + return new WaitTask(_sceneLoaderAsync.TransitionToSceneFromAllAsync(targetSceneReference, intermediateSceneReference).AsTask()); + } + public WaitTask UnloadScenesAsync(ILoadSceneInfo[] sceneReferences) { return new WaitTask(_sceneLoaderAsync.UnloadScenesAsync(sceneReferences).AsTask()); diff --git a/Runtime/SceneLoaders/SceneLoaderUniTask.cs b/Runtime/SceneLoaders/SceneLoaderUniTask.cs index 60c99f6..c2c9d9c 100644 --- a/Runtime/SceneLoaders/SceneLoaderUniTask.cs +++ b/Runtime/SceneLoaders/SceneLoaderUniTask.cs @@ -35,6 +35,26 @@ public void TransitionToScene(ILoadSceneInfo targetSceneInfo, ILoadSceneInfo int TransitionToSceneAsync(targetSceneInfo, intermediateSceneInfo); } + public void TransitionToScenesFromScenes(ILoadSceneInfo[] targetScenes, ILoadSceneInfo[] fromScenes, int setIndexActive, ILoadSceneInfo intermediateSceneInfo = null) + { + TransitionToScenesFromScenesAsync(targetScenes, fromScenes, setIndexActive, intermediateSceneInfo); + } + + public void TransitionToSceneFromScenes(ILoadSceneInfo targetSceneInfo, ILoadSceneInfo[] fromScenes, ILoadSceneInfo intermediateSceneInfo = null) + { + TransitionToSceneFromScenesAsync(targetSceneInfo, fromScenes, intermediateSceneInfo); + } + + public void TransitionToScenesFromAll(ILoadSceneInfo[] targetScenes, int setIndexActive, ILoadSceneInfo intermediateSceneInfo = null) + { + TransitionToScenesFromAllAsync(targetScenes, setIndexActive, intermediateSceneInfo); + } + + public void TransitionToSceneFromAll(ILoadSceneInfo targetSceneInfo, ILoadSceneInfo intermediateSceneInfo = null) + { + TransitionToSceneFromAllAsync(targetSceneInfo, intermediateSceneInfo); + } + public void UnloadScenes(ILoadSceneInfo[] sceneInfos) { UnloadScenesAsync(sceneInfos); @@ -65,6 +85,26 @@ public UniTask TransitionToSceneAsync(ILoadSceneInfo targetSceneReference return _sceneLoaderAsync.TransitionToSceneAsync(targetSceneReference, intermediateSceneReference).AsTask().AsUniTask(); } + public UniTask TransitionToScenesFromScenesAsync(ILoadSceneInfo[] targetScenes, ILoadSceneInfo[] fromScenes, int setIndexActive, ILoadSceneInfo intermediateSceneReference = null) + { + return _sceneLoaderAsync.TransitionToScenesFromScenesAsync(targetScenes, fromScenes, setIndexActive, intermediateSceneReference).AsTask().AsUniTask(); + } + + public UniTask TransitionToSceneFromScenesAsync(ILoadSceneInfo targetSceneReference, ILoadSceneInfo[] fromScenes, ILoadSceneInfo intermediateSceneReference = null) + { + return _sceneLoaderAsync.TransitionToSceneFromScenesAsync(targetSceneReference, fromScenes, intermediateSceneReference).AsTask().AsUniTask(); + } + + public UniTask TransitionToScenesFromAllAsync(ILoadSceneInfo[] targetScenes, int setIndexActive, ILoadSceneInfo intermediateSceneReference = null) + { + return _sceneLoaderAsync.TransitionToScenesFromAllAsync(targetScenes, setIndexActive, intermediateSceneReference).AsTask().AsUniTask(); + } + + public UniTask TransitionToSceneFromAllAsync(ILoadSceneInfo targetSceneReference, ILoadSceneInfo intermediateSceneReference = null) + { + return _sceneLoaderAsync.TransitionToSceneFromAllAsync(targetSceneReference, intermediateSceneReference).AsTask().AsUniTask(); + } + public UniTask UnloadScenesAsync(ILoadSceneInfo[] sceneReferences) { return _sceneLoaderAsync.UnloadScenesAsync(sceneReferences).AsTask().AsUniTask(); diff --git a/Tests/Runtime/SceneLoaderTests.cs b/Tests/Runtime/SceneLoaderTests.cs index 660d709..0db1343 100644 --- a/Tests/Runtime/SceneLoaderTests.cs +++ b/Tests/Runtime/SceneLoaderTests.cs @@ -162,6 +162,98 @@ void sceneLoaded(Scene scene) } } + [UnityTest] + public IEnumerator TransitionToScenesFromScenes([ValueSource(nameof(_sceneLoaders))] ISceneLoader sceneLoader, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.MultipleLoadSceneInfoList))] ILoadSceneInfo[] targetScenes, [ValueSource(nameof(LoadingSceneInfos))] ILoadSceneInfo loadingScene) + { + int sceneCount = targetScenes.Length; + + var loadedScenes = new List(sceneCount); + + sceneLoader.Manager.SceneLoaded += sceneLoaded; + sceneLoader.LoadScenes(targetScenes); + + var watch = new Stopwatch(); + watch.Start(); + yield return new WaitUntil(() => loadedScenes.Count == sceneCount || watch.ElapsedMilliseconds > SceneTestEnvironment.DefaultTimeout); + watch.Stop(); + + sceneCount += loadingScene == null ? 0 : 1; + + var unloadedScenes = new List(sceneCount); + sceneLoader.Manager.SceneUnloaded += sceneUnloaded; + + loadedScenes.Clear(); + sceneLoader.TransitionToScenesFromScenes(targetScenes, targetScenes, 0, loadingScene); + + watch.Restart(); + yield return new WaitUntil(() => (loadedScenes.Count == sceneCount && unloadedScenes.Count == sceneCount) || watch.ElapsedMilliseconds > SceneTestEnvironment.DefaultTimeout); + watch.Stop(); + + sceneLoader.Manager.SceneLoaded -= sceneLoaded; + sceneLoader.Manager.SceneUnloaded -= sceneUnloaded; + + yield return new WaitUntil(() => sceneLoader.Manager.TotalSceneCount == targetScenes.Length); + + Assert.AreEqual(sceneCount, loadedScenes.Count); + Assert.AreEqual(sceneCount, unloadedScenes.Count); + + void sceneLoaded(Scene scene) + { + loadedScenes.Add(scene); + } + + void sceneUnloaded(Scene scene) + { + unloadedScenes.Add(scene); + } + } + + [UnityTest] + public IEnumerator TransitionToScenesFromAll([ValueSource(nameof(_sceneLoaders))] ISceneLoader sceneLoader, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.MultipleLoadSceneInfoList))] ILoadSceneInfo[] targetScenes, [ValueSource(nameof(LoadingSceneInfos))] ILoadSceneInfo loadingScene) + { + int sceneCount = targetScenes.Length; + + var loadedScenes = new List(sceneCount); + + sceneLoader.Manager.SceneLoaded += sceneLoaded; + sceneLoader.LoadScenes(targetScenes); + + var watch = new Stopwatch(); + watch.Start(); + yield return new WaitUntil(() => loadedScenes.Count == sceneCount || watch.ElapsedMilliseconds > SceneTestEnvironment.DefaultTimeout); + watch.Stop(); + + sceneCount += loadingScene == null ? 0 : 1; + + var unloadedScenes = new List(sceneCount); + sceneLoader.Manager.SceneUnloaded += sceneUnloaded; + + loadedScenes.Clear(); + sceneLoader.TransitionToScenesFromAll(targetScenes, 0, loadingScene); + + watch.Restart(); + yield return new WaitUntil(() => (loadedScenes.Count == sceneCount && unloadedScenes.Count == sceneCount) || watch.ElapsedMilliseconds > SceneTestEnvironment.DefaultTimeout); + watch.Stop(); + + sceneLoader.Manager.SceneLoaded -= sceneLoaded; + sceneLoader.Manager.SceneUnloaded -= sceneUnloaded; + + yield return new WaitUntil(() => sceneLoader.Manager.TotalSceneCount == targetScenes.Length); + + Assert.AreEqual(sceneCount, loadedScenes.Count); + Assert.AreEqual(sceneCount, unloadedScenes.Count); + + void sceneLoaded(Scene scene) + { + loadedScenes.Add(scene); + } + + void sceneUnloaded(Scene scene) + { + unloadedScenes.Add(scene); + } + } + [UnityTest] public IEnumerator Transition([ValueSource(nameof(_sceneLoaders))] ISceneLoader sceneLoader, [ValueSource(typeof(SceneTestEnvironment), nameof(SceneTestEnvironment.SingleLoadSceneInfoList))] ILoadSceneInfo targetScene, [ValueSource(nameof(LoadingSceneInfos))] ILoadSceneInfo loadingScene) {