SceneManager.cs 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508
  1. //------------------------------------------------------------
  2. // Game Framework
  3. // Copyright © 2013-2021 loyalsoft. All rights reserved.
  4. // Homepage: http://www.game7000.com/
  5. // Feedback: http://www.game7000.com/
  6. //------------------------------------------------------------
  7. using GameFramework.Resource;
  8. using System;
  9. using System.Collections.Generic;
  10. namespace GameFramework.Scene
  11. {
  12. /// <summary>
  13. /// 场景管理器。
  14. /// </summary>
  15. internal sealed class SceneManager : GameFrameworkModule, ISceneManager
  16. {
  17. private readonly List<string> m_LoadedSceneAssetNames;
  18. private readonly List<string> m_LoadingSceneAssetNames;
  19. private readonly List<string> m_UnloadingSceneAssetNames;
  20. private readonly LoadSceneCallbacks m_LoadSceneCallbacks;
  21. private readonly UnloadSceneCallbacks m_UnloadSceneCallbacks;
  22. private IResourceManager m_ResourceManager;
  23. private EventHandler<LoadSceneSuccessEventArgs> m_LoadSceneSuccessEventHandler;
  24. private EventHandler<LoadSceneFailureEventArgs> m_LoadSceneFailureEventHandler;
  25. private EventHandler<LoadSceneUpdateEventArgs> m_LoadSceneUpdateEventHandler;
  26. private EventHandler<LoadSceneDependencyAssetEventArgs> m_LoadSceneDependencyAssetEventHandler;
  27. private EventHandler<UnloadSceneSuccessEventArgs> m_UnloadSceneSuccessEventHandler;
  28. private EventHandler<UnloadSceneFailureEventArgs> m_UnloadSceneFailureEventHandler;
  29. /// <summary>
  30. /// 初始化场景管理器的新实例。
  31. /// </summary>
  32. public SceneManager()
  33. {
  34. m_LoadedSceneAssetNames = new List<string>();
  35. m_LoadingSceneAssetNames = new List<string>();
  36. m_UnloadingSceneAssetNames = new List<string>();
  37. m_LoadSceneCallbacks = new LoadSceneCallbacks(LoadSceneSuccessCallback, LoadSceneFailureCallback, LoadSceneUpdateCallback, LoadSceneDependencyAssetCallback);
  38. m_UnloadSceneCallbacks = new UnloadSceneCallbacks(UnloadSceneSuccessCallback, UnloadSceneFailureCallback);
  39. m_ResourceManager = null;
  40. m_LoadSceneSuccessEventHandler = null;
  41. m_LoadSceneFailureEventHandler = null;
  42. m_LoadSceneUpdateEventHandler = null;
  43. m_LoadSceneDependencyAssetEventHandler = null;
  44. m_UnloadSceneSuccessEventHandler = null;
  45. m_UnloadSceneFailureEventHandler = null;
  46. }
  47. /// <summary>
  48. /// 获取游戏框架模块优先级。
  49. /// </summary>
  50. /// <remarks>优先级较高的模块会优先轮询,并且关闭操作会后进行。</remarks>
  51. internal override int Priority
  52. {
  53. get
  54. {
  55. return 2;
  56. }
  57. }
  58. /// <summary>
  59. /// 加载场景成功事件。
  60. /// </summary>
  61. public event EventHandler<LoadSceneSuccessEventArgs> LoadSceneSuccess
  62. {
  63. add
  64. {
  65. m_LoadSceneSuccessEventHandler += value;
  66. }
  67. remove
  68. {
  69. m_LoadSceneSuccessEventHandler -= value;
  70. }
  71. }
  72. /// <summary>
  73. /// 加载场景失败事件。
  74. /// </summary>
  75. public event EventHandler<LoadSceneFailureEventArgs> LoadSceneFailure
  76. {
  77. add
  78. {
  79. m_LoadSceneFailureEventHandler += value;
  80. }
  81. remove
  82. {
  83. m_LoadSceneFailureEventHandler -= value;
  84. }
  85. }
  86. /// <summary>
  87. /// 加载场景更新事件。
  88. /// </summary>
  89. public event EventHandler<LoadSceneUpdateEventArgs> LoadSceneUpdate
  90. {
  91. add
  92. {
  93. m_LoadSceneUpdateEventHandler += value;
  94. }
  95. remove
  96. {
  97. m_LoadSceneUpdateEventHandler -= value;
  98. }
  99. }
  100. /// <summary>
  101. /// 加载场景时加载依赖资源事件。
  102. /// </summary>
  103. public event EventHandler<LoadSceneDependencyAssetEventArgs> LoadSceneDependencyAsset
  104. {
  105. add
  106. {
  107. m_LoadSceneDependencyAssetEventHandler += value;
  108. }
  109. remove
  110. {
  111. m_LoadSceneDependencyAssetEventHandler -= value;
  112. }
  113. }
  114. /// <summary>
  115. /// 卸载场景成功事件。
  116. /// </summary>
  117. public event EventHandler<UnloadSceneSuccessEventArgs> UnloadSceneSuccess
  118. {
  119. add
  120. {
  121. m_UnloadSceneSuccessEventHandler += value;
  122. }
  123. remove
  124. {
  125. m_UnloadSceneSuccessEventHandler -= value;
  126. }
  127. }
  128. /// <summary>
  129. /// 卸载场景失败事件。
  130. /// </summary>
  131. public event EventHandler<UnloadSceneFailureEventArgs> UnloadSceneFailure
  132. {
  133. add
  134. {
  135. m_UnloadSceneFailureEventHandler += value;
  136. }
  137. remove
  138. {
  139. m_UnloadSceneFailureEventHandler -= value;
  140. }
  141. }
  142. /// <summary>
  143. /// 场景管理器轮询。
  144. /// </summary>
  145. /// <param name="elapseSeconds">逻辑流逝时间,以秒为单位。</param>
  146. /// <param name="realElapseSeconds">真实流逝时间,以秒为单位。</param>
  147. internal override void Update(float elapseSeconds, float realElapseSeconds)
  148. {
  149. }
  150. /// <summary>
  151. /// 关闭并清理场景管理器。
  152. /// </summary>
  153. internal override void Shutdown()
  154. {
  155. string[] loadedSceneAssetNames = m_LoadedSceneAssetNames.ToArray();
  156. foreach (string loadedSceneAssetName in loadedSceneAssetNames)
  157. {
  158. if (SceneIsUnloading(loadedSceneAssetName))
  159. {
  160. continue;
  161. }
  162. UnloadScene(loadedSceneAssetName);
  163. }
  164. m_LoadedSceneAssetNames.Clear();
  165. m_LoadingSceneAssetNames.Clear();
  166. m_UnloadingSceneAssetNames.Clear();
  167. }
  168. /// <summary>
  169. /// 设置资源管理器。
  170. /// </summary>
  171. /// <param name="resourceManager">资源管理器。</param>
  172. public void SetResourceManager(IResourceManager resourceManager)
  173. {
  174. if (resourceManager == null)
  175. {
  176. throw new GameFrameworkException("Resource manager is invalid.");
  177. }
  178. m_ResourceManager = resourceManager;
  179. }
  180. /// <summary>
  181. /// 获取场景是否已加载。
  182. /// </summary>
  183. /// <param name="sceneAssetName">场景资源名称。</param>
  184. /// <returns>场景是否已加载。</returns>
  185. public bool SceneIsLoaded(string sceneAssetName)
  186. {
  187. if (string.IsNullOrEmpty(sceneAssetName))
  188. {
  189. throw new GameFrameworkException("Scene asset name is invalid.");
  190. }
  191. return m_LoadedSceneAssetNames.Contains(sceneAssetName);
  192. }
  193. /// <summary>
  194. /// 获取已加载场景的资源名称。
  195. /// </summary>
  196. /// <returns>已加载场景的资源名称。</returns>
  197. public string[] GetLoadedSceneAssetNames()
  198. {
  199. return m_LoadedSceneAssetNames.ToArray();
  200. }
  201. /// <summary>
  202. /// 获取已加载场景的资源名称。
  203. /// </summary>
  204. /// <param name="results">已加载场景的资源名称。</param>
  205. public void GetLoadedSceneAssetNames(List<string> results)
  206. {
  207. if (results == null)
  208. {
  209. throw new GameFrameworkException("Results is invalid.");
  210. }
  211. results.Clear();
  212. results.AddRange(m_LoadedSceneAssetNames);
  213. }
  214. /// <summary>
  215. /// 获取场景是否正在加载。
  216. /// </summary>
  217. /// <param name="sceneAssetName">场景资源名称。</param>
  218. /// <returns>场景是否正在加载。</returns>
  219. public bool SceneIsLoading(string sceneAssetName)
  220. {
  221. if (string.IsNullOrEmpty(sceneAssetName))
  222. {
  223. throw new GameFrameworkException("Scene asset name is invalid.");
  224. }
  225. return m_LoadingSceneAssetNames.Contains(sceneAssetName);
  226. }
  227. /// <summary>
  228. /// 获取正在加载场景的资源名称。
  229. /// </summary>
  230. /// <returns>正在加载场景的资源名称。</returns>
  231. public string[] GetLoadingSceneAssetNames()
  232. {
  233. return m_LoadingSceneAssetNames.ToArray();
  234. }
  235. /// <summary>
  236. /// 获取正在加载场景的资源名称。
  237. /// </summary>
  238. /// <param name="results">正在加载场景的资源名称。</param>
  239. public void GetLoadingSceneAssetNames(List<string> results)
  240. {
  241. if (results == null)
  242. {
  243. throw new GameFrameworkException("Results is invalid.");
  244. }
  245. results.Clear();
  246. results.AddRange(m_LoadingSceneAssetNames);
  247. }
  248. /// <summary>
  249. /// 获取场景是否正在卸载。
  250. /// </summary>
  251. /// <param name="sceneAssetName">场景资源名称。</param>
  252. /// <returns>场景是否正在卸载。</returns>
  253. public bool SceneIsUnloading(string sceneAssetName)
  254. {
  255. if (string.IsNullOrEmpty(sceneAssetName))
  256. {
  257. throw new GameFrameworkException("Scene asset name is invalid.");
  258. }
  259. return m_UnloadingSceneAssetNames.Contains(sceneAssetName);
  260. }
  261. /// <summary>
  262. /// 获取正在卸载场景的资源名称。
  263. /// </summary>
  264. /// <returns>正在卸载场景的资源名称。</returns>
  265. public string[] GetUnloadingSceneAssetNames()
  266. {
  267. return m_UnloadingSceneAssetNames.ToArray();
  268. }
  269. /// <summary>
  270. /// 获取正在卸载场景的资源名称。
  271. /// </summary>
  272. /// <param name="results">正在卸载场景的资源名称。</param>
  273. public void GetUnloadingSceneAssetNames(List<string> results)
  274. {
  275. if (results == null)
  276. {
  277. throw new GameFrameworkException("Results is invalid.");
  278. }
  279. results.Clear();
  280. results.AddRange(m_UnloadingSceneAssetNames);
  281. }
  282. /// <summary>
  283. /// 检查场景资源是否存在。
  284. /// </summary>
  285. /// <param name="sceneAssetName">要检查场景资源的名称。</param>
  286. /// <returns>场景资源是否存在。</returns>
  287. public bool HasScene(string sceneAssetName)
  288. {
  289. return m_ResourceManager.HasAsset(sceneAssetName) != HasAssetResult.NotExist;
  290. }
  291. /// <summary>
  292. /// 加载场景。
  293. /// </summary>
  294. /// <param name="sceneAssetName">场景资源名称。</param>
  295. public void LoadScene(string sceneAssetName)
  296. {
  297. LoadScene(sceneAssetName, Constant.DefaultPriority, null);
  298. }
  299. /// <summary>
  300. /// 加载场景。
  301. /// </summary>
  302. /// <param name="sceneAssetName">场景资源名称。</param>
  303. /// <param name="priority">加载场景资源的优先级。</param>
  304. public void LoadScene(string sceneAssetName, int priority)
  305. {
  306. LoadScene(sceneAssetName, priority, null);
  307. }
  308. /// <summary>
  309. /// 加载场景。
  310. /// </summary>
  311. /// <param name="sceneAssetName">场景资源名称。</param>
  312. /// <param name="userData">用户自定义数据。</param>
  313. public void LoadScene(string sceneAssetName, object userData)
  314. {
  315. LoadScene(sceneAssetName, Constant.DefaultPriority, userData);
  316. }
  317. /// <summary>
  318. /// 加载场景。
  319. /// </summary>
  320. /// <param name="sceneAssetName">场景资源名称。</param>
  321. /// <param name="priority">加载场景资源的优先级。</param>
  322. /// <param name="userData">用户自定义数据。</param>
  323. public void LoadScene(string sceneAssetName, int priority, object userData)
  324. {
  325. if (string.IsNullOrEmpty(sceneAssetName))
  326. {
  327. throw new GameFrameworkException("Scene asset name is invalid.");
  328. }
  329. if (m_ResourceManager == null)
  330. {
  331. throw new GameFrameworkException("You must set resource manager first.");
  332. }
  333. if (SceneIsUnloading(sceneAssetName))
  334. {
  335. throw new GameFrameworkException(Utility.Text.Format("Scene asset '{0}' is being unloaded.", sceneAssetName));
  336. }
  337. if (SceneIsLoading(sceneAssetName))
  338. {
  339. throw new GameFrameworkException(Utility.Text.Format("Scene asset '{0}' is being loaded.", sceneAssetName));
  340. }
  341. if (SceneIsLoaded(sceneAssetName))
  342. {
  343. throw new GameFrameworkException(Utility.Text.Format("Scene asset '{0}' is already loaded.", sceneAssetName));
  344. }
  345. m_LoadingSceneAssetNames.Add(sceneAssetName);
  346. m_ResourceManager.LoadScene(sceneAssetName, priority, m_LoadSceneCallbacks, userData);
  347. }
  348. /// <summary>
  349. /// 卸载场景。
  350. /// </summary>
  351. /// <param name="sceneAssetName">场景资源名称。</param>
  352. public void UnloadScene(string sceneAssetName)
  353. {
  354. UnloadScene(sceneAssetName, null);
  355. }
  356. /// <summary>
  357. /// 卸载场景。
  358. /// </summary>
  359. /// <param name="sceneAssetName">场景资源名称。</param>
  360. /// <param name="userData">用户自定义数据。</param>
  361. public void UnloadScene(string sceneAssetName, object userData)
  362. {
  363. if (string.IsNullOrEmpty(sceneAssetName))
  364. {
  365. throw new GameFrameworkException("Scene asset name is invalid.");
  366. }
  367. if (m_ResourceManager == null)
  368. {
  369. throw new GameFrameworkException("You must set resource manager first.");
  370. }
  371. if (SceneIsUnloading(sceneAssetName))
  372. {
  373. throw new GameFrameworkException(Utility.Text.Format("Scene asset '{0}' is being unloaded.", sceneAssetName));
  374. }
  375. if (SceneIsLoading(sceneAssetName))
  376. {
  377. throw new GameFrameworkException(Utility.Text.Format("Scene asset '{0}' is being loaded.", sceneAssetName));
  378. }
  379. if (!SceneIsLoaded(sceneAssetName))
  380. {
  381. throw new GameFrameworkException(Utility.Text.Format("Scene asset '{0}' is not loaded yet.", sceneAssetName));
  382. }
  383. m_UnloadingSceneAssetNames.Add(sceneAssetName);
  384. m_ResourceManager.UnloadScene(sceneAssetName, m_UnloadSceneCallbacks, userData);
  385. }
  386. private void LoadSceneSuccessCallback(string sceneAssetName, float duration, object userData)
  387. {
  388. m_LoadingSceneAssetNames.Remove(sceneAssetName);
  389. m_LoadedSceneAssetNames.Add(sceneAssetName);
  390. if (m_LoadSceneSuccessEventHandler != null)
  391. {
  392. LoadSceneSuccessEventArgs loadSceneSuccessEventArgs = LoadSceneSuccessEventArgs.Create(sceneAssetName, duration, userData);
  393. m_LoadSceneSuccessEventHandler(this, loadSceneSuccessEventArgs);
  394. ReferencePool.Release(loadSceneSuccessEventArgs);
  395. }
  396. }
  397. private void LoadSceneFailureCallback(string sceneAssetName, LoadResourceStatus status, string errorMessage, object userData)
  398. {
  399. m_LoadingSceneAssetNames.Remove(sceneAssetName);
  400. string appendErrorMessage = Utility.Text.Format("Load scene failure, scene asset name '{0}', status '{1}', error message '{2}'.", sceneAssetName, status, errorMessage);
  401. if (m_LoadSceneFailureEventHandler != null)
  402. {
  403. LoadSceneFailureEventArgs loadSceneFailureEventArgs = LoadSceneFailureEventArgs.Create(sceneAssetName, appendErrorMessage, userData);
  404. m_LoadSceneFailureEventHandler(this, loadSceneFailureEventArgs);
  405. ReferencePool.Release(loadSceneFailureEventArgs);
  406. return;
  407. }
  408. throw new GameFrameworkException(appendErrorMessage);
  409. }
  410. private void LoadSceneUpdateCallback(string sceneAssetName, float progress, object userData)
  411. {
  412. if (m_LoadSceneUpdateEventHandler != null)
  413. {
  414. LoadSceneUpdateEventArgs loadSceneUpdateEventArgs = LoadSceneUpdateEventArgs.Create(sceneAssetName, progress, userData);
  415. m_LoadSceneUpdateEventHandler(this, loadSceneUpdateEventArgs);
  416. ReferencePool.Release(loadSceneUpdateEventArgs);
  417. }
  418. }
  419. private void LoadSceneDependencyAssetCallback(string sceneAssetName, string dependencyAssetName, int loadedCount, int totalCount, object userData)
  420. {
  421. if (m_LoadSceneDependencyAssetEventHandler != null)
  422. {
  423. LoadSceneDependencyAssetEventArgs loadSceneDependencyAssetEventArgs = LoadSceneDependencyAssetEventArgs.Create(sceneAssetName, dependencyAssetName, loadedCount, totalCount, userData);
  424. m_LoadSceneDependencyAssetEventHandler(this, loadSceneDependencyAssetEventArgs);
  425. ReferencePool.Release(loadSceneDependencyAssetEventArgs);
  426. }
  427. }
  428. private void UnloadSceneSuccessCallback(string sceneAssetName, object userData)
  429. {
  430. m_UnloadingSceneAssetNames.Remove(sceneAssetName);
  431. m_LoadedSceneAssetNames.Remove(sceneAssetName);
  432. if (m_UnloadSceneSuccessEventHandler != null)
  433. {
  434. UnloadSceneSuccessEventArgs unloadSceneSuccessEventArgs = UnloadSceneSuccessEventArgs.Create(sceneAssetName, userData);
  435. m_UnloadSceneSuccessEventHandler(this, unloadSceneSuccessEventArgs);
  436. ReferencePool.Release(unloadSceneSuccessEventArgs);
  437. }
  438. }
  439. private void UnloadSceneFailureCallback(string sceneAssetName, object userData)
  440. {
  441. m_UnloadingSceneAssetNames.Remove(sceneAssetName);
  442. if (m_UnloadSceneFailureEventHandler != null)
  443. {
  444. UnloadSceneFailureEventArgs unloadSceneFailureEventArgs = UnloadSceneFailureEventArgs.Create(sceneAssetName, userData);
  445. m_UnloadSceneFailureEventHandler(this, unloadSceneFailureEventArgs);
  446. ReferencePool.Release(unloadSceneFailureEventArgs);
  447. return;
  448. }
  449. throw new GameFrameworkException(Utility.Text.Format("Unload scene failure, scene asset name '{0}'.", sceneAssetName));
  450. }
  451. }
  452. }