I have a custom scene manager, which apart from loading scenes calls some events for me. I want it to fully load a scene, before it starts loading another one, so I added a lock. I'm using Monitor
because I want to enter the lock in OnLoadScene()
and exit it in LoadSceneAsync()
and this wouldn't be possible with the lock() {}
syntax, because LoadSceneAsync()
is called as a Coroutine
(asynchronously). I found the Monitor
syntax here: C# manual lock/unlock.
Here is the code:
public class CustomSceneManager : Singleton<CustomSceneManager>
{
public delegate void SceneChange(string sceneName);
public event SceneChange LoadScene;
public event SceneChange UnloadScene;
private static readonly object LoadSceneLock = new object();
private IEnumerator LoadSceneAsync(string sceneName)
{
var asyncLoadLevel = SceneManager.LoadSceneAsync(sceneName, LoadSceneMode.Single);
while (!asyncLoadLevel.isDone)
{
yield return null;
}
Debug.Log($"Finished loading: {sceneName}");
LoadScene?.Invoke(sceneName);
Monitor.Exit(LoadSceneLock); // exit lock
}
public void OnLoadScene(string newSceneName)
{
Monitor.Enter(LoadSceneLock); // enter lock
Debug.Log($"Started loading: {newSceneName}");
UnloadScene?.Invoke(newSceneName);
StartCoroutine(LoadSceneAsync(newSceneName));
}
}
The issue is that it doesn't work as I expect it to. This is how my logs look:
Started loading: scene_1
Started loading: scene_2
Finished loading: scene_1
Finished loading: scene_2
Am I using the lock incorrectly?