Skip to content

Commit 5953402

Browse files
committed
fix: correct scene assignment on load/unload ops
1 parent 5d7b9b7 commit 5953402

File tree

5 files changed

+83
-34
lines changed

5 files changed

+83
-34
lines changed

Packages/mygamedevtools-scene-loader/Runtime/Managers/SceneManager.cs

Lines changed: 30 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ public Scene GetLastLoadedScene()
5858
return default;
5959

6060
for (int i = SceneCount - 1; i >= 0; i--)
61-
if (!_unloadingScenes.Contains(_loadedScenes[i]))
61+
if (!_unloadingScenes.Contains(_loadedScenes[i]) && _loadedScenes[i].isLoaded)
6262
return _loadedScenes[i];
6363

6464
return default;
@@ -77,9 +77,6 @@ public Scene GetLoadedSceneByName(string name)
7777
public async ValueTask<Scene> LoadSceneAsync(ILoadSceneInfo sceneInfo, bool setActive = false, IProgress<float> progress = null)
7878
{
7979
var operation = GetLoadSceneOperation(sceneInfo);
80-
Scene loadedScene = default;
81-
82-
UnitySceneManager.sceneLoaded += registerLoadedScene;
8380

8481
#if USE_UNITASK
8582
await operation.ToUniTask(progress);
@@ -91,7 +88,7 @@ public async ValueTask<Scene> LoadSceneAsync(ILoadSceneInfo sceneInfo, bool setA
9188
}
9289
#endif
9390

94-
UnitySceneManager.sceneLoaded -= registerLoadedScene;
91+
var loadedScene = GetLastUnityLoadedSceneByInfo(sceneInfo);
9592

9693
_loadedScenes.Add(loadedScene);
9794
SceneLoaded?.Invoke(loadedScene);
@@ -100,22 +97,17 @@ public async ValueTask<Scene> LoadSceneAsync(ILoadSceneInfo sceneInfo, bool setA
10097
SetActiveScene(loadedScene);
10198

10299
return loadedScene;
103-
104-
void registerLoadedScene(Scene scene, LoadSceneMode loadSceneMode)
105-
{
106-
if (sceneInfo.IsReferenceToScene(scene))
107-
loadedScene = scene;
108-
}
109100
}
110101

111102
public async ValueTask<Scene> UnloadSceneAsync(ILoadSceneInfo sceneInfo)
112103
{
113-
var scene = GetLastLoadedSceneByInfo(sceneInfo);
114-
if (!_loadedScenes.Contains(scene))
115-
throw new InvalidOperationException($"Cannot unload the scene \"{scene.name}\" that has not been loaded through this {GetType().Name}.");
104+
var scene = GetLastSceneByInfo(sceneInfo);
116105
if (_unloadingScenes.Contains(scene))
117106
return await WaitForSceneUnload(scene);
107+
if (!_loadedScenes.Contains(scene))
108+
throw new InvalidOperationException($"Cannot unload the scene \"{scene.name}\" that has not been loaded through this {GetType().Name}.");
118109

110+
_loadedScenes.Remove(scene);
119111
_unloadingScenes.Add(scene);
120112
var operation = GetUnloadSceneOperation(sceneInfo);
121113
#if USE_UNITASK
@@ -126,7 +118,6 @@ public async ValueTask<Scene> UnloadSceneAsync(ILoadSceneInfo sceneInfo)
126118
#endif
127119

128120
_unloadingScenes.Remove(scene);
129-
_loadedScenes.Remove(scene);
130121
if (_activeScene == scene)
131122
SetActiveScene(GetLastLoadedScene());
132123

@@ -170,16 +161,37 @@ AsyncOperation GetUnloadSceneOperation(ILoadSceneInfo sceneInfo)
170161
throw new Exception($"Unexpected {nameof(ILoadSceneInfo.Reference)} type.");
171162
}
172163

173-
Scene GetLastLoadedSceneByInfo(ILoadSceneInfo sceneInfo)
164+
Scene GetLastSceneByInfo(ILoadSceneInfo sceneInfo)
174165
{
175166
var sceneCount = SceneCount;
176-
for (int i = sceneCount - 1; i >= 0; i--)
167+
int i;
168+
for (i = sceneCount - 1; i >= 0; i--)
177169
{
178170
var scene = _loadedScenes[i];
179171
if (sceneInfo.IsReferenceToScene(scene))
180172
return scene;
181173
}
182-
throw new ArgumentException($"Could not find any loaded scene with the provided ILoadSceneInfo: {sceneInfo.Reference}");
174+
175+
sceneCount = _unloadingScenes.Count;
176+
for (i = 0; i < sceneCount; i++)
177+
{
178+
var scene = _unloadingScenes[i];
179+
if (sceneInfo.IsReferenceToScene(scene))
180+
return scene;
181+
}
182+
throw new ArgumentException($"Could not find any scene with the provided ILoadSceneInfo: {sceneInfo}");
183+
}
184+
185+
Scene GetLastUnityLoadedSceneByInfo(ILoadSceneInfo sceneInfo)
186+
{
187+
var sceneCount = UnitySceneManager.sceneCount;
188+
for (int i = sceneCount - 1; i >= 0; i--)
189+
{
190+
var scene = UnitySceneManager.GetSceneAt(i);
191+
if (scene.isLoaded && sceneInfo.IsReferenceToScene(scene))
192+
return scene;
193+
}
194+
throw new ArgumentException($"Could not find any loaded scene in the Unity Scene Manager with the provided ILoadSceneInfo: {sceneInfo}");
183195
}
184196
}
185197
}

Packages/mygamedevtools-scene-loader/Runtime/Managers/SceneManagerAddressable.cs

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ public async ValueTask<Scene> LoadSceneAsync(ILoadSceneInfo sceneInfo, bool setA
106106

107107
public async ValueTask<Scene> UnloadSceneAsync(ILoadSceneInfo sceneInfo)
108108
{
109-
var sceneInstance = GetLastLoadedSceneByInfo(sceneInfo);
109+
var sceneInstance = GetLastSceneByInfo(sceneInfo);
110110
if (!_loadedScenes.Contains(sceneInstance))
111111
throw new InvalidOperationException($"Cannot unload the scene \"{sceneInstance.Scene.name}\" that has not been loaded through this {GetType().Name}.");
112112
if (_unloadingScenes.Contains(sceneInstance))
@@ -117,23 +117,27 @@ public async ValueTask<Scene> UnloadSceneAsync(ILoadSceneInfo sceneInfo)
117117
#if USE_UNITASK
118118
await operation.ToUniTask();
119119
#else
120-
while (!operation.IsDone)
120+
while (operation.IsValid() && !operation.IsDone)
121121
await Task.Yield();
122122
#endif
123123

124-
if (operation.Status == AsyncOperationStatus.Failed)
125-
throw operation.OperationException;
124+
Scene unloadedScene;
126125

127-
var loadedScene = operation.Result.Scene;
126+
if (!operation.IsValid())
127+
unloadedScene = sceneInstance.Scene;
128+
else if (operation.Status == AsyncOperationStatus.Failed)
129+
throw operation.OperationException;
130+
else
131+
unloadedScene = operation.Result.Scene;
128132

129133
_unloadingScenes.Remove(sceneInstance);
130134
_loadedScenes.Remove(sceneInstance);
131135
if (_activeSceneInstance.Scene == sceneInstance.Scene)
132136
SetActiveScene(GetLastLoadedScene());
133137

134-
SceneUnloaded?.Invoke(loadedScene);
138+
SceneUnloaded?.Invoke(unloadedScene);
135139

136-
return loadedScene;
140+
return unloadedScene;
137141
}
138142

139143
async ValueTask<Scene> WaitForSceneUnload(SceneInstance sceneInstance)
@@ -161,16 +165,25 @@ AsyncOperationHandle<SceneInstance> GetLoadSceneOperation(ILoadSceneInfo sceneIn
161165
throw new Exception($"Unexpected {nameof(ILoadSceneInfo.Reference)} type.");
162166
}
163167

164-
SceneInstance GetLastLoadedSceneByInfo(ILoadSceneInfo sceneInfo)
168+
SceneInstance GetLastSceneByInfo(ILoadSceneInfo sceneInfo)
165169
{
166170
var sceneCount = SceneCount;
167-
for (int i = sceneCount - 1; i >= 0; i--)
171+
int i;
172+
for (i = sceneCount - 1; i >= 0; i--)
168173
{
169174
var sceneInstance = _loadedScenes[i];
170175
if (sceneInfo.IsReferenceToScene(sceneInstance.Scene))
171176
return sceneInstance;
172177
}
173-
throw new ArgumentException($"Could not find any loaded scene with the provided ILoadSceneInfo: {sceneInfo.Reference}");
178+
179+
sceneCount = _unloadingScenes.Count;
180+
for (i = 0; i < sceneCount; i++)
181+
{
182+
var sceneInstance = _unloadingScenes[i];
183+
if (sceneInfo.IsReferenceToScene(sceneInstance.Scene))
184+
return sceneInstance;
185+
}
186+
throw new ArgumentException($"Could not find any loaded scene with the provided ILoadSceneInfo: {sceneInfo}");
174187
}
175188

176189
bool ValidateAssetReference(object reference)

Packages/mygamedevtools-scene-loader/Runtime/SceneLoaders/SceneLoaderAsync.cs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@
55
*/
66

77
using System;
8+
using System.Linq;
89
using System.Threading.Tasks;
10+
using UnityEngine;
911
using UnityEngine.SceneManagement;
1012
using Object = UnityEngine.Object;
1113

@@ -45,10 +47,13 @@ async ValueTask<Scene> TransitionDirectlyAsync(ILoadSceneInfo loadSceneInfo, Sce
4547
async ValueTask<Scene> TransitionWithIntermediateAsync(ILoadSceneInfo targetSceneInfo, ILoadSceneInfo intermediateSceneInfo, Scene externalOriginScene)
4648
{
4749
var externalOrigin = externalOriginScene.IsValid();
50+
51+
var loadingScene = await _manager.LoadSceneAsync(intermediateSceneInfo);
52+
intermediateSceneInfo = new LoadSceneInfoScene(loadingScene);
53+
4854
var currentScene = externalOrigin ? externalOriginScene : _manager.GetActiveScene();
49-
await _manager.LoadSceneAsync(intermediateSceneInfo);
5055

51-
var loadingBehavior = Object.FindObjectOfType<LoadingBehavior>();
56+
var loadingBehavior = Object.FindObjectsOfType<LoadingBehavior>().FirstOrDefault(l => l.gameObject.scene == loadingScene);
5257
return loadingBehavior
5358
? await TransitionWithIntermediateLoadingAsync(targetSceneInfo, intermediateSceneInfo, loadingBehavior, currentScene, externalOrigin)
5459
: await TransitionWithIntermediateNoLoadingAsync(targetSceneInfo, intermediateSceneInfo, currentScene, externalOrigin);
@@ -60,6 +65,9 @@ async ValueTask<Scene> TransitionWithIntermediateLoadingAsync(ILoadSceneInfo tar
6065
while (progress.State != LoadingState.Loading)
6166
await Task.Yield();
6267

68+
if (!externalOrigin)
69+
currentScene = _manager.GetActiveScene();
70+
6371
await UnloadCurrentScene(currentScene, externalOrigin);
6472

6573
var loadedScene = await _manager.LoadSceneAsync(targetSceneInfo, true, progress);

Packages/mygamedevtools-scene-loader/Runtime/SceneLoaders/SceneLoaderCoroutine.cs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
using Cysharp.Threading.Tasks;
88
using System;
99
using System.Collections;
10+
using System.Linq;
1011
using UnityEngine;
1112
using UnityEngine.SceneManagement;
1213
using Object = UnityEngine.Object;
@@ -57,10 +58,15 @@ IEnumerator TransitionDirectlyRoutine(ILoadSceneInfo targetSceneInfo, Scene exte
5758
IEnumerator TransitionWithIntermediateRoutine(ILoadSceneInfo targetSceneInfo, ILoadSceneInfo intermediateSceneInfo, Scene externalOriginScene)
5859
{
5960
var externalOrigin = externalOriginScene.IsValid();
61+
62+
var task = _manager.LoadSceneAsync(intermediateSceneInfo).AsTask();
63+
yield return new WaitTask(task);
64+
var loadingScene = task.Result;
65+
intermediateSceneInfo = new LoadSceneInfoScene(loadingScene);
66+
6067
var currentScene = externalOrigin ? externalOriginScene : _manager.GetActiveScene();
61-
yield return new WaitTask(_manager.LoadSceneAsync(intermediateSceneInfo).AsTask());
6268

63-
var loadingBehavior = Object.FindObjectOfType<LoadingBehavior>();
69+
var loadingBehavior = Object.FindObjectsOfType<LoadingBehavior>().FirstOrDefault(l => l.gameObject.scene == loadingScene);
6470
yield return loadingBehavior
6571
? TransitionWithIntermediateLoadingAsync(targetSceneInfo, intermediateSceneInfo, loadingBehavior, currentScene, externalOrigin)
6672
: TransitionWithIntermediateNoLoadingAsync(targetSceneInfo, intermediateSceneInfo, currentScene, externalOrigin);
@@ -71,6 +77,9 @@ IEnumerator TransitionWithIntermediateLoadingAsync(ILoadSceneInfo targetSceneInf
7177
var progress = loadingBehavior.Progress;
7278
yield return new WaitUntil(() => progress.State == LoadingState.Loading);
7379

80+
if (!externalOrigin)
81+
currentScene = _manager.GetActiveScene();
82+
7483
yield return UnloadCurrentScene(currentScene, externalOrigin);
7584

7685
yield return new WaitTask(_manager.LoadSceneAsync(targetSceneInfo, true, progress).AsTask());

Packages/mygamedevtools-scene-loader/Runtime/SceneLoaders/SceneLoaderUniTask.cs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
using Cysharp.Threading.Tasks;
99
using System;
10+
using System.Linq;
1011
using UnityEngine.SceneManagement;
1112
using Object = UnityEngine.Object;
1213

@@ -46,10 +47,13 @@ async UniTask<Scene> TransitionDirectlyAsync(ILoadSceneInfo loadSceneInfo, Scene
4647
async UniTask<Scene> TransitionWithIntermediateAsync(ILoadSceneInfo targetSceneInfo, ILoadSceneInfo intermediateSceneInfo, Scene externalOriginScene)
4748
{
4849
var externalOrigin = externalOriginScene.IsValid();
50+
51+
var loadingScene = await _manager.LoadSceneAsync(intermediateSceneInfo);
52+
intermediateSceneInfo = new LoadSceneInfoScene(loadingScene);
53+
4954
var currentScene = externalOrigin ? externalOriginScene : _manager.GetActiveScene();
50-
await _manager.LoadSceneAsync(intermediateSceneInfo);
5155

52-
var loadingBehavior = Object.FindObjectOfType<LoadingBehavior>();
56+
var loadingBehavior = Object.FindObjectsOfType<LoadingBehavior>().FirstOrDefault(l => l.gameObject.scene == loadingScene);
5357
return loadingBehavior
5458
? await TransitionWithIntermediateLoadingAsync(targetSceneInfo, intermediateSceneInfo, loadingBehavior, currentScene, externalOrigin)
5559
: await TransitionWithIntermediateNoLoadingAsync(targetSceneInfo, intermediateSceneInfo, currentScene, externalOrigin);
@@ -60,6 +64,9 @@ async UniTask<Scene> TransitionWithIntermediateLoadingAsync(ILoadSceneInfo targe
6064
var progress = loadingBehavior.Progress;
6165
await UniTask.WaitUntil(() => progress.State == LoadingState.Loading);
6266

67+
if (!externalOrigin)
68+
currentScene = _manager.GetActiveScene();
69+
6370
await UnloadCurrentScene(currentScene, externalOrigin);
6471

6572
var loadedScene = await _manager.LoadSceneAsync(targetSceneInfo, true, progress);

0 commit comments

Comments
 (0)