ProjectDDD/Assets/_DDD/_Scripts/GameFramework/Scene/SceneManager.cs

127 lines
3.8 KiB
C#
Raw Normal View History

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<SceneManager>, IManager
{
[SerializeField]
private SceneTransitionHandlerSo _sceneTransitionHandlerSo;
private Dictionary<SceneType, SceneInstance> _loadedScenes;
private SceneInstance _currentSceneInstance;
public Action<SceneInstance> OnSceneChanged;
public void PreInit()
{
Array sceneTypeArray = Enum.GetValues(typeof(SceneType));
_loadedScenes = new Dictionary<SceneType, SceneInstance>(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));
}
}
}
}