using System.Collections.Generic; using System.Linq; using Cysharp.Threading.Tasks; using PhxhSDK; using UnityEngine; using UnityEngine.AddressableAssets; using UnityEngine.ResourceManagement.AsyncOperations; using UnityEngine.ResourceManagement.ResourceProviders; using UnityEngine.SceneManagement; namespace Gameplay.SubSystems { /// /// 游戏场景的底层逻辑 /// public class GameSceneManager : Singlenton { public class SceneHandle { public Scene Scene { get; private set; } public SceneHandle(Scene scene) { Scene = scene; } public Camera SceneMainCamera => CommonUtils.GetSceneRootComponent(Scene); } private Dictionary> _sceneOpDic = new(); private string _lastSceneToBeUnload; private string GetPostProcessedScenePath(string scenePath) => PostProcessData.Instance[scenePath]; public async UniTask LoadSceneAsync(string scenePath, LoadSceneMode mode = LoadSceneMode.Single) { scenePath = GetPostProcessedScenePath(scenePath); if (string.IsNullOrEmpty(scenePath)) { DebugUtil.LogError($"ScenePath is null!"); return null; } if (mode == LoadSceneMode.Single) { _sceneOpDic.Clear(); _lastSceneToBeUnload = null; } if (!_sceneOpDic.TryGetValue(scenePath, out var op)) { op = Addressables.LoadSceneAsync(scenePath, mode); _sceneOpDic.Add(scenePath, op); } await op; if (!string.IsNullOrEmpty(_lastSceneToBeUnload)) { UnLoadSceneAsync(_lastSceneToBeUnload); _lastSceneToBeUnload = null; } return new(op.Result.Scene); } public async UniTask UnLoadSceneAsync(string scenePath) { scenePath = GetPostProcessedScenePath(scenePath); if (string.IsNullOrEmpty(scenePath)) { DebugUtil.LogError($"ScenePath is null!"); return; } if (!_sceneOpDic.TryGetValue(scenePath, out var op)) { DebugUtil.LogError($"该场景没有被加载过 scenePath:{scenePath}"); return; } if (_sceneOpDic.Count == 1) { //如果只剩下一个场景了,那么此次unload必然失败,要等到下一次load新场景后重新unload _lastSceneToBeUnload = scenePath; } else { _sceneOpDic.Remove(scenePath); await Addressables.UnloadSceneAsync(op); } } /// /// 返回场景加载的进度 /// /// /// 0-100的浮点数 public float GetSceneLoadingProgress(string scenePath) { scenePath = GetPostProcessedScenePath(scenePath); if (_sceneOpDic.TryGetValue(scenePath, out var op)) { return op.PercentComplete * 100; } return 0; } public SceneHandle GetLoadedSceneHandle(string scenePath) { scenePath = GetPostProcessedScenePath(scenePath); var op = _sceneOpDic.GetValueOrDefault(scenePath); if (op.Status == AsyncOperationStatus.Succeeded) { return new SceneHandle(op.Result.Scene); } return null; } } }