Newer
Older
TheVengeance-Project-IADE-Unity2D / Assets / Scripts / Managers / SceneLoader.cs
  1. using Eflatun.SceneReference;
  2. using System;
  3. using System.Collections;
  4. using System.Collections.Generic;
  5. using UnityEngine;
  6. using UnityEngine.SceneManagement;
  7. namespace MyCollections.SceneManagement
  8. {
  9. public class SceneLoader : MonoBehaviour
  10. {
  11. public SceneGroup[] sceneGroups;
  12. private static SceneLoader instance;
  13. [SerializeField] private GameObject loadingScreen;
  14. [SerializeField] private SceneReference loading;
  15. //Singleton
  16. public static SceneLoader Instance => instance;
  17. private void Awake()
  18. {
  19. if (instance == null)
  20. {
  21. instance = this;
  22. DontDestroyOnLoad(gameObject);
  23. }
  24. else
  25. {
  26. Destroy(gameObject);
  27. }
  28. }
  29. private void Start()
  30. {
  31. }
  32. private SceneGroup FindSceneGroupByName(string name) =>
  33. Array.Find(sceneGroups, group => group.groupName == name);
  34. public void LoadScenes(string groupName, LoadType type)
  35. {
  36. SceneGroup sceneGroup = FindSceneGroupByName(groupName);
  37. switch (type)
  38. {
  39. case LoadType.Loading:
  40. StartCoroutine(LoadWithLoadingScreenAsync(sceneGroup));
  41. break;
  42. case LoadType.Trigger:
  43. LoadSceneGroup(groupName);
  44. break;
  45. }
  46. }
  47. public void LoadSceneTrigger(SceneReference sceneReference)
  48. {
  49. int count = SceneManager.sceneCount;
  50. for (int i = 0; i < count; i++)
  51. {
  52. Scene scene = SceneManager.GetSceneAt(i);
  53. if (scene.name == sceneReference.Name) return;
  54. }
  55. Debug.LogWarning("LoadingScene: " + sceneReference.Name);
  56. SceneManager.LoadSceneAsync(sceneReference.Name, LoadSceneMode.Additive);
  57. }
  58. public void UnloadSceneTrigger(SceneReference unloadScene, SceneReference newActiveScene)
  59. {
  60. int count = SceneManager.sceneCount;
  61. bool isSceneLoaded = false;
  62. for (int i = 0; i < count; i++)
  63. {
  64. Scene scene = SceneManager.GetSceneAt(i);
  65. if (scene.name == unloadScene.Name)
  66. {
  67. isSceneLoaded = true;
  68. break;
  69. }
  70. }
  71. if (!isSceneLoaded)
  72. {
  73. Debug.LogWarning("Scene to unload not loaded: " + unloadScene.Name);
  74. return;
  75. }
  76. SceneManager.UnloadSceneAsync(unloadScene.Name);
  77. SetActiveScene(newActiveScene);
  78. }
  79. private void SetActiveScene(SceneReference sceneReference)
  80. {
  81. int count = SceneManager.sceneCount;
  82. for (int i = 0; i < count; i++)
  83. {
  84. Scene scene = SceneManager.GetSceneAt(i);
  85. if (scene.name == sceneReference.Name)
  86. {
  87. SceneManager.SetActiveScene(scene);
  88. return;
  89. }
  90. }
  91. }
  92. public void LoadSceneWithLoading(SceneReference sceneToLoad, SceneReference sceneToUnload) =>
  93. StartCoroutine(LoadSceneWithLoadingScreen(sceneToLoad, sceneToUnload));
  94. public void LoadSceneGroup(string groupName)
  95. {
  96. SceneGroup group = FindSceneGroupByName(groupName);
  97. Debug.Log($"Group Found: {group.groupName}");
  98. if (group == null)
  99. return;
  100. List<string> scenesToLoad = new List<string>();
  101. int count = SceneManager.sceneCount;
  102. Debug.Log($"Scene Count: {count}");
  103. for (int i = 0; i < group.scenes.Count; i++)
  104. {
  105. bool isSceneLoaded = false;
  106. for (int j = 0; j < count; j++)
  107. {
  108. Scene loadedScene = SceneManager.GetSceneAt(j);
  109. if (loadedScene.name == group.scenes[i].Name)
  110. {
  111. isSceneLoaded = true;
  112. break;
  113. }
  114. }
  115. if (!isSceneLoaded)
  116. {
  117. Debug.Log($"Scene to Load Added: {group.scenes[i].Name}");
  118. scenesToLoad.Add(group.scenes[i].Name);
  119. }
  120. }
  121. StartCoroutine(LoadAndSetActiveScene(scenesToLoad, group));
  122. }
  123. private IEnumerator LoadSceneWithLoadingScreen(SceneReference sceneToLoad, SceneReference sceneToUnload)
  124. {
  125. string sceneName = loading.Name;
  126. //Load the Loading Scene
  127. AsyncOperation op = SceneManager.LoadSceneAsync(sceneName, LoadSceneMode.Additive);
  128. //Wait until the Loading Scene is loaded
  129. yield return new WaitUntil(() => op.isDone);
  130. // Update scene count dynamically
  131. int s = SceneManager.sceneCount;
  132. //Get the loading screen
  133. GameObject loadingCanvas = GameObject.FindGameObjectWithTag("LoadingCanvas");
  134. loadingScreen = loadingCanvas.transform.GetChild(0).gameObject;
  135. if (loadingScreen == null)
  136. {
  137. Debug.LogError("Loading Screen is Null");
  138. yield break;
  139. }
  140. //Enables the login screen
  141. loadingScreen.SetActive(true); //Automatically will trigger the fadeout animation
  142. Animator animator;
  143. //Try to get the animator from the loading screen
  144. if (!loadingScreen.TryGetComponent(out animator))
  145. {
  146. Debug.LogError("Animator is Null");
  147. yield break;
  148. }
  149. AnimatorStateInfo stateInfo = animator.GetCurrentAnimatorStateInfo(0);
  150. float duration = stateInfo.length;
  151. //Wait for the rest of the loading screen animation to finish
  152. yield return new WaitForSeconds(duration);
  153. //Unloads the current activeScene
  154. SceneManager.UnloadSceneAsync(sceneToUnload.Name);
  155. //Loads the scene
  156. AsyncOperation loadSceneOp = SceneManager.LoadSceneAsync(sceneToLoad.Name, LoadSceneMode.Additive);
  157. //Wait until the operation is done
  158. yield return new WaitUntil(() => loadSceneOp.isDone);
  159. //We invoke the fadeout animation of the loading screen
  160. animator.SetTrigger("FadeOut");
  161. //Get the current state info
  162. stateInfo = animator.GetCurrentAnimatorStateInfo(0);
  163. duration = stateInfo.length; //get the state lenght
  164. //Wait for the animation to finish
  165. yield return new WaitForSeconds(duration);
  166. //After the animation is finished
  167. //we unload the Loading screen
  168. AsyncOperation unloadOp = SceneManager.UnloadSceneAsync(sceneName);
  169. yield return new WaitUntil(() => unloadOp.isDone);
  170. }
  171. private IEnumerator LoadWithLoadingScreenAsync(SceneGroup group)
  172. {
  173. List<string> scenesToLoad = new List<string>();
  174. string sceneName = loading.Name; //Get the scene name
  175. //Load the Loading Scene
  176. AsyncOperation op = SceneManager.LoadSceneAsync(sceneName, LoadSceneMode.Additive);
  177. //Wait until the Loading Scene is loaded
  178. yield return new WaitUntil(() => op.isDone);
  179. // Update scene count dynamically
  180. int s = SceneManager.sceneCount;
  181. //Get the loading screen
  182. GameObject loadingCanvas = GameObject.FindGameObjectWithTag("LoadingCanvas");
  183. loadingScreen = loadingCanvas.transform.GetChild(0).gameObject;
  184. if (loadingScreen == null)
  185. {
  186. Debug.LogError("Loading Screen is Null");
  187. yield break;
  188. }
  189. //Enables the login screen
  190. loadingScreen.SetActive(true); //Automatically will trigger the fadeout animation
  191. Animator animator;
  192. //Try to get the animator from the loading screen
  193. if (!loadingScreen.TryGetComponent(out animator))
  194. {
  195. Debug.LogError("Animator is Null");
  196. yield break;
  197. }
  198. AnimatorStateInfo stateInfo = animator.GetCurrentAnimatorStateInfo(0);
  199. float duration = stateInfo.length;
  200. //Wait for the rest of the loading screen animation to finish
  201. yield return new WaitForSeconds(duration);
  202. //Get the all the scenes to Load
  203. for (int i = 0; i < group.scenes.Count; i++)
  204. {
  205. bool isSceneLoaded = false;
  206. // Update scene count dynamically
  207. int currentSceneCount = SceneManager.sceneCount;
  208. Debug.Log($"Current Scene Count: {currentSceneCount}");
  209. for (int j = 0; j < currentSceneCount; j++)
  210. {
  211. //Get the Scene at index in the SceneManager's list of loaded Scenes
  212. Scene loadedScene = SceneManager.GetSceneAt(j);
  213. Debug.Log($"LoadedScene: {loadedScene.name}");
  214. // Skip checking if it's the "Loading" scene, which should only be loaded once
  215. if (loadedScene.name == sceneName)
  216. {
  217. continue; // Skip the loading scene
  218. }
  219. //Compare the names of the SceneManager's list with the group of scenes
  220. if (loadedScene.name == group.scenes[i].Name)
  221. {
  222. //if the scene is loaded flags to true
  223. Debug.Log($"The Scene is Loaded: {loadedScene.name}");
  224. isSceneLoaded = true;
  225. break;
  226. }
  227. }
  228. //Adds the scenes to load list
  229. if (!isSceneLoaded)
  230. {
  231. Debug.Log($"Scene to Load Added: {group.scenes[i].Name}");
  232. scenesToLoad.Add(group.scenes[i].Name);
  233. }
  234. }
  235. //Unload scenes
  236. UnloadScene(group);
  237. //load the all the scenes
  238. for (int i = 0; i < scenesToLoad.Count; i++)
  239. {
  240. AsyncOperation loadSceneOp = SceneManager.LoadSceneAsync(scenesToLoad[i], LoadSceneMode.Additive);
  241. //Wait until the operation is done
  242. yield return new WaitUntil(() => loadSceneOp.isDone);
  243. //Set active the scene
  244. SceneManager.SetActiveScene(SceneManager.GetSceneByName(scenesToLoad[i]));
  245. }
  246. //We invoke the fadeout animation of the loading screen
  247. animator.SetTrigger("FadeOut");
  248. //Get the current state info
  249. stateInfo = animator.GetCurrentAnimatorStateInfo(0);
  250. duration = stateInfo.length; //get the state lenght
  251. //Wait for the animation to finish
  252. yield return new WaitForSeconds(duration);
  253. //After the animation is finished
  254. //we unload the Loading screen
  255. AsyncOperation unloadOp = SceneManager.UnloadSceneAsync(sceneName);
  256. yield return new WaitUntil(() => unloadOp.isDone);
  257. }
  258. private IEnumerator LoadAndSetActiveScene(List<string> scenesToLoad, SceneGroup group)
  259. {
  260. for (int i = 0; i < scenesToLoad.Count; i++)
  261. {
  262. AsyncOperation op = SceneManager.LoadSceneAsync(scenesToLoad[i], LoadSceneMode.Additive);
  263. Debug.Log($"Loading Scene: {scenesToLoad[i]}");
  264. // Wait for the scene to fully load
  265. yield return new WaitUntil(() => op.isDone);
  266. // After the scene has loaded, set it as active
  267. SceneManager.SetActiveScene(SceneManager.GetSceneByName(scenesToLoad[i]));
  268. Debug.Log($"Scene {scenesToLoad[i]} set as active.");
  269. }
  270. // Once all scenes are loaded, unload the required scenes
  271. UnloadScene(group);
  272. }
  273. private void UnloadScene(SceneGroup group)
  274. {
  275. List<Scene> scenesToUnload = group.FindSceneRefByType(SceneType.DisableScene);
  276. Debug.Log($"Scenes Found To Unload: {scenesToUnload.Count}");
  277. List<string> unloadScenes = new List<string>();
  278. if (scenesToUnload.Count == 0)
  279. return;
  280. for (int i = 0; i < scenesToUnload.Count; i++)
  281. {
  282. Scene sceneToUnload = scenesToUnload[i];
  283. if (sceneToUnload.isLoaded)
  284. {
  285. Debug.Log($"Scene to Unload: {sceneToUnload.name}");
  286. unloadScenes.Add(sceneToUnload.name);
  287. }
  288. }
  289. if (unloadScenes.Count > 0)
  290. {
  291. for (int i = 0; i < unloadScenes.Count; i++)
  292. {
  293. SceneManager.UnloadSceneAsync(unloadScenes[i]);
  294. Debug.Log($"Unloading Scene: {unloadScenes[i]}");
  295. }
  296. }
  297. }
  298. }
  299. [Serializable]
  300. public struct SceneDataSaver
  301. {
  302. //Position where the player should be after changing scene
  303. public Vector3 position;
  304. public string groupName;
  305. }
  306. //The trigger loadtype doesn't affect the player gameplay
  307. //The Loading loadtype triggers a loading screen
  308. public enum LoadType
  309. {
  310. Trigger,
  311. Loading
  312. }
  313. public enum SceneAction
  314. {
  315. LoadScene,
  316. UnloadScene
  317. }
  318. }