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 => Scene.GetRootGameObjects() .FirstOrDefault(r => r.GetComponent() != null)?.GetComponent(); } public enum EnumScene { GameStart, // 登录场景 GameMain, // 主场景 GameLevel // 关卡(战场)场景 } public const string SCENE_PREFIX = "Assets/Scenes/"; public const string START_SCENE_NAME = "StartScene"; public const string LEVEL_SCENE_NAME = "LevelScene"; public const string MAIN_SCENE_NAME = "MainScene"; public const string SCENE_SUFFIX = ".unity"; private Dictionary> _sceneOpDic = new(); public async UniTask ChangeScene(EnumScene enumScene) { string sceneName = SCENE_PREFIX; switch (enumScene) { case EnumScene.GameStart: sceneName += START_SCENE_NAME; break; case EnumScene.GameMain: sceneName += MAIN_SCENE_NAME; break; case EnumScene.GameLevel: sceneName += LEVEL_SCENE_NAME; break; default: DebugUtil.LogError("{0}.ChangeScene, {1} has no scene name matched", GetType(), enumScene); sceneName += START_SCENE_NAME; break; } sceneName += SCENE_SUFFIX; await LoadSceneAsync(sceneName); return LoadingResult.Success; } public async UniTask LoadSceneAsync(string scenePath, LoadSceneMode mode = LoadSceneMode.Single) { if (string.IsNullOrEmpty(scenePath)) { DebugUtil.LogError($"ScenePath is null!"); return null; } if (mode == LoadSceneMode.Single) _sceneOpDic.Clear(); if (!_sceneOpDic.TryGetValue(scenePath, out var op)) { op = Addressables.LoadSceneAsync(scenePath, mode); _sceneOpDic.Add(scenePath, op); } await op.ToUniTask(); return new(op.Result.Scene); } public async UniTask UnLoadSceneAsync(string scenePath) { if (string.IsNullOrEmpty(scenePath)) { DebugUtil.LogError($"ScenePath is null!"); return; } if (!_sceneOpDic.TryGetValue(scenePath, out var op)) { Debug.LogError($"该场景没有被加载过 scenePath:{scenePath}"); return; } _sceneOpDic.Remove(scenePath); await Addressables.UnloadSceneAsync(op).ToUniTask(); } public float GetSceneLoadingProgress(string scenePath) { if (_sceneOpDic.TryGetValue(scenePath, out var op)) { return op.PercentComplete; } return 0; } /// /// 打开UI预览场景,当某个UI需要单独渲染场景时使用(如PVP布阵,营地等) /// 此时场景中的相机会只渲染UI场景内的物件 /// /// /// /// public async UniTask LoadSceneForUIView(string scenePath, LoadSceneMode mode = LoadSceneMode.Single) { var sceneHandle = await LoadSceneAsync(scenePath, mode); if (sceneHandle == null) { return null; } var scene = sceneHandle.Scene; var groundLayer = LayerMask.NameToLayer("Ground"); var UIViewLayer = LayerMask.NameToLayer("UIView"); var UIViewMask = LayerMask.GetMask("UIView","Ground"); //调整所有物品的层级 var roots = scene.GetRootGameObjects(); foreach (var root in roots) { //将所有gameObject设置为UIView层 root.SetLayerEx(UIViewLayer,groundLayer); } //设置相机的culling mask foreach (var root in roots) { var cam = root.GetComponent(); if (!cam) continue; cam.cullingMask = UIViewMask; } //设置光源culling mask var lights = Object.FindObjectsOfType(); foreach (var light in lights) { if (light.gameObject.scene != scene) continue; light.cullingMask = UIViewMask; } //切换全局GI SceneManager.SetActiveScene(scene); var result = new SceneHandle(scene); //CameraManager.Instance.AddCameraStack(sceneHandle.SceneMainCamera); sceneHandle.SceneMainCamera.targetTexture = CameraManager.Instance.MainCamera.targetTexture; return result; } } }