OldBlueWater/BlueWater/Assets/Doozy/Runtime/SceneManagement/SceneLoader.cs

672 lines
31 KiB
C#
Raw Normal View History

// Copyright (c) 2015 - 2023 Doozy Entertainment. All Rights Reserved.
// This code can only be used under the standard Unity Asset Store End User License Agreement
// A Copy of the EULA APPENDIX 1 is available at http://unity3d.com/company/legal/as_terms
using System;
using System.Collections;
using System.Collections.Generic;
using Doozy.Runtime.Common;
using Doozy.Runtime.Common.Attributes;
using Doozy.Runtime.Common.Events;
using Doozy.Runtime.Common.Extensions;
using Doozy.Runtime.Common.Utils;
using Doozy.Runtime.Global;
using Doozy.Runtime.Mody;
using Doozy.Runtime.Reactor;
using Doozy.Runtime.SceneManagement.ScriptableObjects;
using Doozy.Runtime.Signals;
using UnityEngine;
using UnityEngine.SceneManagement;
using Object = UnityEngine.Object;
// ReSharper disable MemberCanBePrivate.Global
// ReSharper disable UnusedMember.Local
namespace Doozy.Runtime.SceneManagement
{
/// <summary>
/// Loads any Scene either by scene name or scene build index and updates a Progressor to show the loading progress.
/// It can also trigger a set of 'actions' when the scene started loading (at 0% load progress) and/or when the scene has been loaded (but not activated) (at 90% load progress)
/// </summary>
[AddComponentMenu("Doozy/Scene Management/Scene Loader")]
public class SceneLoader : MonoBehaviour
{
#if UNITY_EDITOR
[UnityEditor.MenuItem("GameObject/Doozy/Scene Management/Scene Loader", false, 9)]
private static void CreateComponent(UnityEditor.MenuCommand menuCommand)
{
GameObjectUtils.AddToScene<SceneLoader>(false, true);
}
#endif
public enum State
{
/// <summary> Idle mode </summary>
Idle,
/// <summary> Starting to load a scene </summary>
LoadScene,
/// <summary> Is in the process of loading a scene </summary>
Loading,
/// <summary> Has finished loading a scene, but has not activated it yet </summary>
SceneLoaded,
/// <summary> Is activating the loaded scene </summary>
ActivatingScene
}
/// <summary> Stream category name </summary>
public const string k_StreamCategory = "SceneManagement";
/// <summary> Stream name </summary>
public const string k_StreamName = nameof(SceneLoader);
public const GetSceneBy k_DefaultGetSceneBy = GetSceneBy.Name;
public const LoadSceneMode k_DefaultLoadSceneMode = LoadSceneMode.Single;
public const bool k_DefaultAutoSceneActivation = true;
public const bool k_DefaultPreventLoadingSameScene = false;
public const bool k_DefaultSelfDestructAfterSceneLoaded = false;
public const float k_DefaultSceneActivationDelay = 0.2f;
public const int k_DefaultBuildIndex = 0;
public const string k_DefaultSceneName = "";
/// <summary> Database used to keep track of all the SceneLoaders </summary>
[ClearOnReload]
public static HashSet<SceneLoader> database { get; } = new HashSet<SceneLoader>();
[ClearOnReload]
private static SignalStream s_stream;
/// <summary> Signal stream for this component type </summary>
public static SignalStream stream => s_stream ??= SignalsService.GetStream(k_StreamCategory, k_StreamName);
/// <summary> Reference to the SceneManagement global settings </summary>
public static SceneManagementSettings settings => SceneManagementSettings.instance;
/// <summary> Debug flag </summary>
public bool debug => DebugMode | settings.DebugMode;
/// <summary> Enable relevant debug messages to be printed to the console </summary>
public bool DebugMode;
/// <summary> Invoked when a scene started loading </summary>
public ModyEvent OnLoadScene = new ModyEvent(nameof(OnLoadScene));
/// <summary>
/// Invoked when the scene has been loaded (the progress is at 0.9 (90%))
/// and has not been activated yet (the reset 0.1 (10%)).
/// <para/>
/// When loading a scene, Unity first loads the scene (load progress from 0% to 90%)
/// and then activates it (load progress from 90% to 100%). It's a two state process.
/// <para/>
/// This action is triggered after the scene has been loaded
/// and before its activation (at 90% load progress)
/// </summary>
public ModyEvent OnSceneLoaded = new ModyEvent(nameof(OnSceneLoaded));
/// <summary>
/// Invoked after a scene was loaded and then activated.
/// <para/>
/// When loading a scene, Unity first loads the scene (load progress from 0% to 90%)
/// and then activates it (load progress from 90% to 100%). It's a two state process.
/// <para/>
/// This action is triggered after the scene has been loaded and activated.
/// </summary>
public ModyEvent OnSceneActivated = new ModyEvent(nameof(OnSceneActivated));
/// <summary> Event triggered when an async operation is running and its progress has been updated. </summary>
public FloatEvent OnProgressChanged = new FloatEvent();
/// <summary> Keeps track and manages the asyncOperation started when the scene loader begins to load a scene </summary>
public AsyncOperation currentAsyncOperation { get; private set; }
[SerializeField] private bool AllowSceneActivation = k_DefaultAutoSceneActivation;
/// <summary>
/// Allow Scenes to be activated as soon as it is ready. <para/>
/// When loading a scene, Unity first loads the scene (load progress from 0% to 90%) and then activates it (load progress from 90% to 100%). It's a two state process. <para/>
/// This option can stop the scene activation (at 90% load progress), after the scene has been loaded and is ready. <para/>
/// Useful if you need to load several scenes at once and activate them in a specific order and/or at a specific time.
/// </summary>
public bool allowSceneActivation
{
get => AllowSceneActivation;
set => AllowSceneActivation = value;
}
[SerializeField] private bool PreventLoadingSameScene = k_DefaultPreventLoadingSameScene;
/// <summary> Prevent loading a scene that is already loaded. </summary>
public bool preventLoadingSameScene
{
get => PreventLoadingSameScene;
set => PreventLoadingSameScene = value;
}
/// <summary> Determines what load method this SceneLoader will use by default if the load scene method is called without any parameters </summary>
public GetSceneBy GetSceneBy = k_DefaultGetSceneBy;
/// <summary> Determines how the new scene is loaded by this SceneLoader if the load scene method is called without any parameters </summary>
public LoadSceneMode LoadSceneMode = k_DefaultLoadSceneMode;
[SerializeField] private List<Progressor> Progressors;
/// <summary> Progressors updated when the scene loader progress changes. </summary>
public List<Progressor> progressors => Progressors ?? (Progressors = new List<Progressor>());
/// <summary> If an async operation is running, it returns the current load progress (float between 0 and 1) </summary>
public float progress
{
get => m_Progress;
private set
{
// Debugger.Log($"progress: {value}");
m_Progress = value;
progressors.ForEach(p => p.PlayToProgress(value));
OnProgressChanged?.Invoke(value);
}
}
/// <summary>
/// Sets for how long will the SceneLoader wait, after a scene has been loaded, before it starts the scene activation process (works only if AllowSceneActivation is enabled).
/// <para />
/// When loading a scene, Unity first loads the scene (load progress from 0% to 90%) and then activates it (load progress from 90% to 100%). It's a two state process.
/// <para />
/// This delay is after the scene has been loaded and before its activation (at 90% load progress)
/// </summary>
public float SceneActivationDelay = k_DefaultSceneActivationDelay;
/// <summary> Index of the Scene in the Build Settings to load (when GetSceneBy is set to GetSceneBy.BuildIndex) </summary>
public int SceneBuildIndex = k_DefaultBuildIndex;
/// <summary> Name or path of the Scene to load (when GetSceneBy is set to GetSceneBy.Name) </summary>
public string SceneName = k_DefaultSceneName;
/// <summary> Mark this SceneLoader to self destruct (to destroy itself) after it loads a Scene </summary>
public bool SelfDestructAfterSceneLoaded = k_DefaultSelfDestructAfterSceneLoaded;
private State m_CurrentState = State.Idle;
/// <summary> Current state the SceneLoader is in </summary>
public State currentState
{
get => m_CurrentState;
private set
{
bool stateChanged = m_CurrentState != value;
m_CurrentState = value;
if (stateChanged) stream?.SendSignal(new SceneLoaderSignalData(this));
}
}
private bool m_LoadInProgress; //keeps track if a scene load process is currently running
private bool m_SceneLoadedAndReady; //mark that the scene has not been loaded (load progress has not reached 90%)
private bool m_ActivatingScene; //TRUE when a scene is being activated
private float m_SceneLoadedAndReadyTime; //
private float m_Progress; //updated when an async operation is running (float between 0 and 1)
private void Awake() =>
database.Add(this);
private void OnEnable()
{
database.Remove(null);
ResetProgress();
}
private void OnDestroy()
{
database.Remove(null);
database.Remove(this);
}
private void Update()
{
if (currentAsyncOperation == null) return;
float calculatedProgress = Mathf.Clamp01(currentAsyncOperation.progress / 0.9f); //update load progress [0, 0.9] > [0, 1]
if (Math.Abs(progress - calculatedProgress) > 0.0001f) progress = calculatedProgress;
if (debug && !m_ActivatingScene & !m_SceneLoadedAndReady) Log($"Load progress: {Mathf.Round(progress * 100)}%");
if (!m_SceneLoadedAndReady & !m_ActivatingScene)
currentState = State.Loading;
// ReSharper disable once CompareOfFloatsByEqualityOperator
if (!m_SceneLoadedAndReady && currentAsyncOperation.progress == 0.9f) // Loading completed
{
if (debug) Log($"Scene finished loading and is ready to be activated.");
OnSceneLoaded?.Execute();
currentState = State.SceneLoaded;
m_SceneLoadedAndReady = true; //mark that the scene has been loaded and is now ready to be activated (bool needed to stop LoadBehavior.OnSceneLoaded.Invoke(gameObject) from executing more than once)
m_SceneLoadedAndReadyTime = Time.realtimeSinceStartup;
}
if (m_SceneLoadedAndReady && !m_ActivatingScene && AllowSceneActivation)
{
if (SceneActivationDelay < 0) SceneActivationDelay = 0; //sanity check
if (SceneActivationDelay >= 0 && Time.realtimeSinceStartup - m_SceneLoadedAndReadyTime > SceneActivationDelay)
ActivateLoadedScene();
}
if (m_ActivatingScene)
currentState = State.ActivatingScene;
if (!currentAsyncOperation.isDone) return;
if (debug) Log($"Loaded scene has been activated.");
OnSceneActivated?.Execute();
m_LoadInProgress = false;
currentAsyncOperation = null;
currentState = State.Idle;
if (SelfDestructAfterSceneLoaded) Coroutiner.Start(SelfDestruct());
}
/// <summary>
/// Check if the scene with the given name or path is loaded.
/// </summary>
/// <param name="sceneName"> Scene name </param>
public static bool IsSceneLoaded(string sceneName)
{
for (int i = 0; i < SceneManager.sceneCount; i++)
{
Scene scene = SceneManager.GetSceneAt(i);
if (scene.name == sceneName) return true;
}
return false;
}
/// <summary>
/// Check if the scene with the given build index is loaded.
/// </summary>
/// <param name="sceneBuildIndex"> Scene build index </param>
public static bool IsSceneLoaded(int sceneBuildIndex)
{
for (int i = 0; i < SceneManager.sceneCount; i++)
{
Scene scene = SceneManager.GetSceneAt(i);
if (scene.buildIndex == sceneBuildIndex) return true;
}
return false;
}
/// <summary>
/// Activate the current loaded scene.
/// <para />
/// Works only if the SceneLoader has loaded a scene and its AllowSceneActivation option is set to false.
/// <para />
/// This method enables the 'allowSceneActivation' for the CurrentAsyncOperation that has been paused at 90%.
/// <para />
/// When loading a scene, Unity first loads the scene (load progress from 0% to 90%) and then activates it (load progress from 90% to 100%). It's a two state process.
/// <para />
/// This method is meant to be used for after the scene has been loaded and before its activation (at 90% load progress).
/// </summary>
public SceneLoader ActivateLoadedScene()
{
if (currentAsyncOperation == null) return this; //no load process is running
if (debug) Log($"Activating Scene...");
m_ActivatingScene = true;
currentState = State.ActivatingScene;
currentAsyncOperation.allowSceneActivation = true;
return this;
}
/// <summary> Loads the Scene, with the current settings </summary>
public SceneLoader LoadScene()
{
// ReSharper disable once SwitchStatementMissingSomeCases
switch (GetSceneBy)
{
case GetSceneBy.Name:
if (preventLoadingSameScene && IsSceneLoaded(SceneName)) return this;
SceneManager.LoadScene(SceneName, LoadSceneMode);
break;
case GetSceneBy.BuildIndex:
if (preventLoadingSameScene && IsSceneLoaded(SceneBuildIndex)) return this;
SceneManager.LoadScene(SceneBuildIndex, LoadSceneMode);
break;
}
return this;
}
/// <summary> Loads the Scene, with the current settings, asynchronously in the background </summary>
public SceneLoader LoadSceneAsync()
{
// ReSharper disable once SwitchStatementMissingSomeCases
switch (GetSceneBy)
{
case GetSceneBy.Name:
if (preventLoadingSameScene && IsSceneLoaded(SceneName)) return this;
LoadSceneAsync(SceneName, LoadSceneMode);
break;
case GetSceneBy.BuildIndex:
if (preventLoadingSameScene && IsSceneLoaded(SceneBuildIndex)) return this;
LoadSceneAsync(SceneBuildIndex, LoadSceneMode);
break;
}
return this;
}
/// <summary> Loads a Scene asynchronously in the background, by its index in Build Settings </summary>
/// <param name="sceneBuildIndex"> Index, in the Build Settings, of the Scene to load </param>
/// <param name="mode"> If LoadSceneMode.Single then all current Scenes will be unloaded before activating the newly loaded scene </param>
public SceneLoader LoadSceneAsync(int sceneBuildIndex, LoadSceneMode mode)
{
if (preventLoadingSameScene && IsSceneLoaded(sceneBuildIndex)) return this;
currentAsyncOperation = SceneManager.LoadSceneAsync(sceneBuildIndex, mode);
StartSceneLoad();
return this;
}
/// <summary> Loads a Scene asynchronously in the background, by its name in Build Settings </summary>
/// <param name="sceneName"> Name or path of the Scene to load </param>
/// <param name="mode"> If LoadSceneMode.Single then all current Scenes will be unloaded before activating the newly loaded scene </param>
public SceneLoader LoadSceneAsync(string sceneName, LoadSceneMode mode)
{
if (preventLoadingSameScene && IsSceneLoaded(sceneName)) return this;
currentAsyncOperation = SceneManager.LoadSceneAsync(sceneName, mode);
StartSceneLoad();
return this;
}
/// <summary> Loads the given scene asynchronously in the background. </summary>
/// <param name="scene"> Scene to load </param>
/// <param name="mode"> If LoadSceneMode.Single then all current Scenes will be unloaded before activating the newly loaded scene </param>
public SceneLoader LoadSceneAsync(Scene scene, LoadSceneMode mode)
{
if (preventLoadingSameScene && IsSceneLoaded(scene.name)) return this;
currentAsyncOperation = SceneManager.LoadSceneAsync(scene.name, mode);
StartSceneLoad();
return this;
}
/// <summary> Loads a Scene asynchronously in the background, by its index in Build Settings, with the LoadSceneMode.Additive setting </summary>
/// <param name="sceneBuildIndex"> Index, in the Build Settings, of the Scene to load </param>
public SceneLoader LoadSceneAsyncAdditive(int sceneBuildIndex) =>
LoadSceneAsync(sceneBuildIndex, LoadSceneMode.Additive);
/// <summary> Loads a Scene asynchronously in the background, by its name in Build Settings, with the LoadSceneMode.Additive setting </summary>
/// <param name="sceneName"> Name or path of the Scene to load </param>
public SceneLoader LoadSceneAsyncAdditive(string sceneName) =>
LoadSceneAsync(sceneName, LoadSceneMode.Additive);
/// <summary> Loads the given scene asynchronously in the background, with the LoadSceneMode.Additive setting. </summary>
/// <param name="scene"> Scene to load </param>
public SceneLoader LoadSceneAsyncAdditive(Scene scene) =>
LoadSceneAsync(scene, LoadSceneMode.Additive);
/// <summary> Loads a Scene asynchronously in the background, by its index in Build Settings, with the LoadSceneMode.Single setting </summary>
/// <param name="sceneBuildIndex"> Index, in the Build Settings, of the Scene to load </param>
public SceneLoader LoadSceneAsyncSingle(int sceneBuildIndex) =>
LoadSceneAsync(sceneBuildIndex, LoadSceneMode.Single);
/// <summary> Loads a Scene asynchronously in the background, by its name in Build Settings, with the LoadSceneMode.Single setting </summary>
/// <param name="sceneName"> Name or path of the Scene to load </param>
public SceneLoader LoadSceneAsyncSingle(string sceneName) =>
LoadSceneAsync(sceneName, LoadSceneMode.Single);
/// <summary> Loads the given scene asynchronously in the background, with the LoadSceneMode.Single setting. </summary>
/// <param name="scene"> Scene to load </param>
public SceneLoader LoadSceneAsyncSingle(Scene scene) =>
LoadSceneAsync(scene, LoadSceneMode.Single);
/// <summary> Set the AllowSceneActivation that that allows for a Scene to be activated as soon as it is ready </summary>
/// <param name="whenReadyAllowSceneActivation"> Allow Scenes to be activated as soon as it is ready </param>
public SceneLoader SetAllowSceneActivation(bool whenReadyAllowSceneActivation)
{
allowSceneActivation = whenReadyAllowSceneActivation;
return this;
}
/// <summary> Set the GetSceneBy value, that determines what load method this SceneLoader will use by default </summary>
/// <param name="getSceneBy"> Load method this SceneLoader will use if the load scene method is called without any parameters </param>
public SceneLoader SetLoadSceneBy(GetSceneBy getSceneBy)
{
GetSceneBy = getSceneBy;
return this;
}
/// <summary> Set the LoadSceneMode value, that determines how the new scene is loaded by this SceneLoader </summary>
/// <param name="loadSceneMode"> Load mode used when loading a scene </param>
public SceneLoader SetLoadSceneMode(LoadSceneMode loadSceneMode)
{
LoadSceneMode = loadSceneMode;
return this;
}
/// <summary> Add a Progressor reference that will get updates when this SceneLoader loads a scene </summary>
/// <param name="progressor"> The Progressor that will get updates when this SceneLoader loads a scene </param>
public SceneLoader AddProgressor(Progressor progressor)
{
if (progressor == null) return this;
progressors.RemoveNulls();
if (progressors.Contains(progressor)) return this;
progressors.Add(progressor);
return this;
}
/// <summary> Remove a Progressor reference that would get updates when this SceneLoader loads a scene </summary>
/// <param name="progressor"> The Progressor that would get updates when this SceneLoader loads a scene </param>
public SceneLoader RemoveProgressor(Progressor progressor)
{
if (progressor == null) return this;
progressors.RemoveNulls();
if (!progressors.Contains(progressor)) return this;
progressors.Remove(progressor);
return this;
}
/// <summary> Clear the Progressor references that would get updates when this SceneLoader loads a scene </summary>
public SceneLoader ClearProgressors()
{
progressors.Clear();
return this;
}
/// <summary> Set the activation delay that determines how long will the SceneLoader wait, after a scene has been loaded, before it starts the scene activation process (works only if AllowSceneActivation is enabled) </summary>
/// <param name="sceneActivationDelay"> How long will the SceneLoader wait, after a scene has been loaded, before it starts the scene activation process </param>
public SceneLoader SetSceneActivationDelay(float sceneActivationDelay)
{
SceneActivationDelay = sceneActivationDelay;
return this;
}
/// <summary> Set the SceneBuildIndex, in the Build Settings, of the Scene to load </summary>
/// <param name="sceneBuildIndex"> Index, in the Build Settings, of the Scene to load </param>
public SceneLoader SetSceneBuildIndex(int sceneBuildIndex)
{
SceneBuildIndex = sceneBuildIndex;
return this;
}
/// <summary> Set the SceneName, name or path, of the Scene to load </summary>
/// <param name="sceneName"> Name or path of the Scene to load </param>
public SceneLoader SetSceneName(string sceneName)
{
SceneName = sceneName;
return this;
}
/// <summary> Set this SceneLoader to self destruct (to destroy itself) after it loads a Scene </summary>
/// <param name="selfDestruct"> Should this SceneLoader self destruct? </param>
public SceneLoader SetSelfDestructAfterSceneLoaded(bool selfDestruct)
{
SelfDestructAfterSceneLoaded = selfDestruct;
return this;
}
/// <summary> Sets the scene load Progress to zero </summary>
private void ResetProgress()
{
progressors.RemoveNulls();
progressors.ForEach(p => p.SetProgressAtZero());
progress = 0;
}
private void StartSceneLoad()
{
ResetProgress();
OnLoadScene?.Execute();
currentState = State.LoadScene;
currentAsyncOperation.allowSceneActivation = false; //update the scene activation mode
m_LoadInProgress = true; //mark that a scene load process is running
m_SceneLoadedAndReady = false; //mark that the scene has not been loaded (load progress has not reached 90%)
m_ActivatingScene = false;
}
private IEnumerator AsynchronousLoad(string sceneName, LoadSceneMode mode)
{
// yield return null;
ResetProgress();
OnLoadScene?.Execute();
currentAsyncOperation = SceneManager.LoadSceneAsync(sceneName, mode);
if (currentAsyncOperation == null) yield break;
currentAsyncOperation.allowSceneActivation = false; //update the scene activation mode
m_LoadInProgress = true; //mark that a scene load process is running
bool sceneLoadedAndReady = false; //mark that the scene has not been loaded (load progress has not reached 90%)
bool activatingScene = false;
// while (!currentAsyncOperation.isDone)
while (m_LoadInProgress)
{
//if (currentAsyncOperation == null) yield break;
// [0, 0.9] > [0, 1]
progress = Mathf.Clamp01(currentAsyncOperation.progress / 0.9f); //update load progress
if (debug && !activatingScene) Log($"Load progress: {Mathf.Round(progress * 100)}%");
// Loading completed
// ReSharper disable once CompareOfFloatsByEqualityOperator
if (!sceneLoadedAndReady && currentAsyncOperation.progress == 0.9f)
{
// progress = 1f;
if (debug) Log($"Scene is ready to be activated.");
OnSceneLoaded.Execute();
sceneLoadedAndReady = true; //mark that the scene has been loaded and is now ready to be activated (bool needed to stop LoadBehavior.OnSceneLoaded.Invoke(gameObject) from executing more than once)
}
if (sceneLoadedAndReady && !activatingScene)
{
if (SceneActivationDelay < 0) SceneActivationDelay = 0; //sanity check
if (SceneActivationDelay > 0) yield return new WaitForSecondsRealtime(SceneActivationDelay);
if (AllowSceneActivation)
{
ActivateLoadedScene();
activatingScene = true;
}
}
if (currentAsyncOperation.isDone)
{
if (debug) Log($"Scene has been activated.");
m_LoadInProgress = false;
// currentAsyncOperation = null;
if (SelfDestructAfterSceneLoaded) Coroutiner.Start(SelfDestruct());
}
yield return null;
}
}
private IEnumerator AsynchronousLoad(int sceneBuildIndex, LoadSceneMode mode)
{
// yield return null;
ResetProgress();
OnLoadScene?.Execute();
currentAsyncOperation = SceneManager.LoadSceneAsync(sceneBuildIndex, mode);
if (currentAsyncOperation == null) yield break;
currentAsyncOperation.allowSceneActivation = false; //update the scene activation mode
m_LoadInProgress = true; //mark that a scene load process is running
bool sceneLoadedAndReady = false; //mark that the scene has not been loaded (load progress has not reached 90%)
bool activatingScene = false;
// while (!currentAsyncOperation.isDone)
while (m_LoadInProgress)
{
//if (currentAsyncOperation == null) yield break;
// [0, 0.9] > [0, 1]
progress = Mathf.Clamp01(currentAsyncOperation.progress / 0.9f); //update load progress
if (debug && !activatingScene) Log($"Load progress: {Mathf.Round(progress * 100)}%");
// Loading completed
// ReSharper disable once CompareOfFloatsByEqualityOperator
if (!sceneLoadedAndReady && currentAsyncOperation.progress == 0.9f)
{
// progress = 1f;
if (debug) Log($"Scene is ready to be activated.");
OnSceneLoaded?.Execute();
sceneLoadedAndReady = true; //mark that the scene has been loaded and is now ready to be activated (bool needed to stop LoadBehavior.OnSceneLoaded.Invoke(gameObject) from executing more than once)
}
if (sceneLoadedAndReady && !activatingScene && AllowSceneActivation)
{
if (SceneActivationDelay < 0) SceneActivationDelay = 0; //sanity check
if (SceneActivationDelay > 0) yield return new WaitForSecondsRealtime(SceneActivationDelay);
ActivateLoadedScene();
activatingScene = true;
}
if (currentAsyncOperation.isDone)
{
if (debug) Log("[" + name + "] Scene has been activated.");
m_LoadInProgress = false;
// currentAsyncOperation = null;
if (SelfDestructAfterSceneLoaded)
{
Coroutiner.Start(SelfDestruct());
}
}
yield return null;
}
}
private IEnumerator SelfDestruct()
{
yield return null;
Destroy(gameObject);
}
/// <summary>
/// Activates all the loaded scenes for all the SceneLoaders that have scenes ready to be activated.
/// <para/>
/// A scene is ready to be activated if the load progress is at 0.9 (90%).
/// </summary>
public static void ActivateLoadedScenes()
{
if (settings.DebugMode) Log($"Activate Loaded Scenes", null);
database.Remove(null);
foreach (SceneLoader sceneLoader in database)
sceneLoader.ActivateLoadedScene();
}
/// <summary> Creates a new GameObject with a SceneLoader script attached and then returns the reference to the newly created script </summary>
/// <param name="parent"> Sets a parent for the newly created GameObject </param>
public static SceneLoader GetLoader(Transform parent = null)
{
SceneLoader loader = new GameObject(nameof(SceneLoader)).AddComponent<SceneLoader>();
if (parent != null)
{
loader.transform.SetParent(parent);
return loader;
}
DontDestroyOnLoad(loader); //make sure this game object is not destroyed when loading a new scene
return loader;
}
private void Log(string message) =>
Log($"[{name}] {message}", this);
private static void Log(string message, Object context) =>
Debugger.Log($"({nameof(SceneLoader)}) {message}", context);
}
}