using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using UnityEngine; using UnityEngine.ResourceManagement.ResourceProviders; namespace DDD { public enum SceneType { Entry = 0, Restaurant = 1, Voyage = 2 } public class SceneManager : Singleton, IManager { [SerializeField] private SceneTransitionHandlerSo _sceneTransitionHandlerSo; private Dictionary _loadedScenes; private SceneInstance _currentSceneInstance; public Action OnSceneChanged; public void PreInit() { Array sceneTypeArray = Enum.GetValues(typeof(SceneType)); _loadedScenes = new Dictionary(sceneTypeArray.Length); } public async Task Init() { try { foreach (SceneType sceneType in Enum.GetValues(typeof(SceneType))) { if (sceneType == SceneType.Entry) continue; await PreloadSceneAsync(sceneType); } } catch (Exception e) { Debug.LogWarning($"Scene preload failed\n{e}"); } } public void PostInit() { } public SceneInstance GetSceneInstance(SceneType sceneType) => _loadedScenes[sceneType]; public async Task PreloadSceneAsync(SceneType sceneType) { if (_loadedScenes.ContainsKey(sceneType)) return; string key = sceneType.ToString(); SceneInstance sceneInstance = await AssetManager.LoadScene(key); if (sceneInstance.Scene.IsValid()) { _loadedScenes[sceneType] = sceneInstance; foreach (var root in sceneInstance.Scene.GetRootGameObjects()) { root.SetActive(false); } } else { Debug.LogError($"[SceneManager] Failed to preload scene: {sceneType}"); } } public async Task ActivateScene(SceneType sceneType) { foreach (var handler in _sceneTransitionHandlerSo.Handlers.Where(handler => handler != null)) { await handler.OnBeforeSceneActivate(sceneType); } if (_loadedScenes.TryGetValue(sceneType, out var sceneInstance)) { foreach (var root in sceneInstance.Scene.GetRootGameObjects()) { root.SetActive(true); } UnityEngine.SceneManagement.SceneManager.SetActiveScene(sceneInstance.Scene); _currentSceneInstance = sceneInstance; } else { Debug.LogError($"[SceneManager] Scene not loaded: {sceneType}"); } foreach (var handler in _sceneTransitionHandlerSo.Handlers.Where(handler => handler != null)) { await handler.OnAfterSceneActivate(sceneType); } } public void DeactivateScene(SceneType sceneType) { if (_loadedScenes.TryGetValue(sceneType, out var sceneInstance)) { foreach (var root in sceneInstance.Scene.GetRootGameObjects()) { root.SetActive(false); } } } public async Task UnloadSceneAsync(SceneType sceneType) { if (_loadedScenes.TryGetValue(sceneType, out var sceneInstance)) { await AssetManager.UnloadScene(GetSceneInstance(sceneType)); } } } }