From 2b6b425903cc77470f657690c09cd434c646bd53 Mon Sep 17 00:00:00 2001 From: NTG_Lenovo Date: Fri, 1 Aug 2025 19:20:38 +0900 Subject: [PATCH] =?UTF-8?q?SceneType=20=EC=A0=9C=EA=B1=B0=20=EB=B2=84?= =?UTF-8?q?=EC=A0=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../_DDD/_Scripts/GameFlow/GameFlowManager.cs | 27 +-- .../GameFlow/GameFlowSceneMappingSo.cs | 3 +- .../Scene/FadeSceneTransitionHandlerSo.cs | 4 +- .../GameFramework/Scene/SceneManager.cs | 180 ++++++++++-------- .../Scene/SceneTransitionHandler.cs | 4 +- 5 files changed, 112 insertions(+), 106 deletions(-) diff --git a/Assets/_DDD/_Scripts/GameFlow/GameFlowManager.cs b/Assets/_DDD/_Scripts/GameFlow/GameFlowManager.cs index 847407daf..3f6a49d0e 100644 --- a/Assets/_DDD/_Scripts/GameFlow/GameFlowManager.cs +++ b/Assets/_DDD/_Scripts/GameFlow/GameFlowManager.cs @@ -49,7 +49,7 @@ public void ChangeFlow(GameFlowState newFlowState) EndCurrentFlow(); - ReadyNewFlow(newFlowState); + _ = ReadyNewFlow(newFlowState); } private bool CanChangeFlow(GameFlowState newFlowState) @@ -62,7 +62,7 @@ private void EndCurrentFlow() } - private async void ReadyNewFlow(GameFlowState newFlowState) + private async Task ReadyNewFlow(GameFlowState newFlowState) { GameFlowDataSo.CurrentGameState = newFlowState; @@ -71,33 +71,26 @@ private async void ReadyNewFlow(GameFlowState newFlowState) await handler.OnReadyNewFlow(newFlowState); } - OpenFlowScene(newFlowState); + await OpenFlowScene(newFlowState); StartFlow(); } - private async void OpenFlowScene(GameFlowState newFlowState) + private async Task OpenFlowScene(GameFlowState newFlowState) { - try + if (GetFlowScene(newFlowState)) { - if (GetFlowScene(newFlowState, out var sceneToLoad)) - { - await SceneManager.Instance.ActivateScene(sceneToLoad); - } - else - { - Debug.Assert(false, "Scene not found!"); - } + await SceneManager.Instance.ActivateScene(newFlowState); } - catch (Exception e) + else { - Debug.LogError(e.Message); + Debug.Assert(false, "Scene not found!"); } } - private bool GetFlowScene(GameFlowState flowState, out SceneType sceneType) + private bool GetFlowScene(GameFlowState flowState) { - return GameFlowSceneMappingSo.FlowToSceneMapping.TryGetValue(flowState, out sceneType); + return GameFlowSceneMappingSo.FlowToSceneMapping.ContainsKey(flowState); } private void StartFlow() diff --git a/Assets/_DDD/_Scripts/GameFlow/GameFlowSceneMappingSo.cs b/Assets/_DDD/_Scripts/GameFlow/GameFlowSceneMappingSo.cs index 78f6393b2..7acec799d 100644 --- a/Assets/_DDD/_Scripts/GameFlow/GameFlowSceneMappingSo.cs +++ b/Assets/_DDD/_Scripts/GameFlow/GameFlowSceneMappingSo.cs @@ -9,7 +9,6 @@ namespace DDD [CreateAssetMenu(fileName = "GameFlowSceneMappingSo", menuName = "GameFlow/GameFlowSceneMappingSo")] public class GameFlowSceneMappingSo : SerializedScriptableObject { - public Dictionary FlowToSceneMapping = new(); - public Dictionary AssetMapping = new(); + public Dictionary FlowToSceneMapping = new(); } } \ No newline at end of file diff --git a/Assets/_DDD/_Scripts/GameFramework/Scene/FadeSceneTransitionHandlerSo.cs b/Assets/_DDD/_Scripts/GameFramework/Scene/FadeSceneTransitionHandlerSo.cs index 75968582c..b463aac31 100644 --- a/Assets/_DDD/_Scripts/GameFramework/Scene/FadeSceneTransitionHandlerSo.cs +++ b/Assets/_DDD/_Scripts/GameFramework/Scene/FadeSceneTransitionHandlerSo.cs @@ -15,7 +15,7 @@ public class FadeSceneTransitionHandlerSo : SceneTransitionHandler [SerializeField] private float _fadeInDuration = 0.5f; - public override async Task OnBeforeSceneActivate(SceneType sceneType) + public override async Task OnBeforeSceneActivate() { var evt = GameEvents.FadeOutEvent; evt.Duration = _fadeOutDuration; @@ -23,7 +23,7 @@ public override async Task OnBeforeSceneActivate(SceneType sceneType) await evt.WaitAsync(); } - public override async Task OnAfterSceneActivate(SceneType sceneType) + public override async Task OnAfterSceneActivate() { float seconds = _delayBeforeFadeIn * 1000; await Task.Delay((int)(seconds)); diff --git a/Assets/_DDD/_Scripts/GameFramework/Scene/SceneManager.cs b/Assets/_DDD/_Scripts/GameFramework/Scene/SceneManager.cs index 6f9eb3b03..5deb51d14 100644 --- a/Assets/_DDD/_Scripts/GameFramework/Scene/SceneManager.cs +++ b/Assets/_DDD/_Scripts/GameFramework/Scene/SceneManager.cs @@ -6,19 +6,12 @@ using UnityEditor; #endif using UnityEngine; +using UnityEngine.AddressableAssets; using UnityEngine.ResourceManagement.ResourceProviders; using UnityEngine.SceneManagement; namespace DDD { - public enum SceneType - { - None = 0, - Entry = 1, - Restaurant = 2, - Voyage = 3 - } - public class SceneData { public Scene Scene { get; } @@ -36,45 +29,39 @@ public class SceneManager : Singleton, IManager [SerializeField] private SceneTransitionHandlerSo _sceneTransitionHandlerSo; - private Dictionary _loadedSceneDatas; - private SceneType _currentSceneType = SceneType.None; + private readonly Dictionary _loadedSceneDatas = new(); + private readonly Dictionary _assetKeyToSceneData = new(); public void PreInit() { - Array sceneTypeArray = Enum.GetValues(typeof(SceneType)); - _loadedSceneDatas = new Dictionary(sceneTypeArray.Length - 1); + _loadedSceneDatas.Clear(); + _assetKeyToSceneData.Clear(); } public async Task Init() { var activeScene = UnityEngine.SceneManagement.SceneManager.GetActiveScene(); - var activeScenePath = activeScene.path; #if UNITY_EDITOR - foreach (var sceneAssetPair in GameFlowManager.Instance.GameFlowSceneMappingSo.AssetMapping) + var flowToSceneMapping = GameFlowManager.Instance.GameFlowSceneMappingSo.FlowToSceneMapping; + + foreach (var pair in flowToSceneMapping) { - var asset = sceneAssetPair.Value.editorAsset; - if (asset == null) continue; + var editorAsset = pair.Value.editorAsset; + if (editorAsset == null) continue; - string assetPath = AssetDatabase.GetAssetPath(asset); - if (string.IsNullOrWhiteSpace(assetPath)) continue; - - if (assetPath == activeScenePath) + var path = AssetDatabase.GetAssetPath(editorAsset); + if (string.IsNullOrWhiteSpace(path) == false && path == activeScene.path) { - _currentSceneType = sceneAssetPair.Key; - _loadedSceneDatas.Add(_currentSceneType, new SceneData(activeScene, null)); + var data = new SceneData(activeScene, null); + _loadedSceneDatas[pair.Key] = data; + _assetKeyToSceneData[GetRuntimeKey(pair.Value)] = data; break; } } - - if (_currentSceneType == SceneType.None) - { - Debug.LogWarning($"[SceneManager] 활성 씬이 AssetMapping에 존재하지 않습니다: {activeScenePath}"); - } #else - _currentSceneType = SceneType.Entry; - _loadedSceneDatas.Add(_currentSceneType, new SceneData(activeScene, null)); + var data = new SceneData(activeScene, null); + _loadedSceneDatas[GameFlowState.None] = data; #endif - await PreloadAll(); } @@ -83,90 +70,111 @@ public void PostInit() } - public async Task PreloadSceneBySceneType(SceneType sceneType) + public async Task PreloadScene(GameFlowState gameFlowState) { - if (_loadedSceneDatas.ContainsKey(sceneType)) return; + if (_loadedSceneDatas.ContainsKey(gameFlowState)) return; - var kvp = GameFlowManager.Instance.GameFlowSceneMappingSo.AssetMapping.FirstOrDefault(kvp => kvp.Key == sceneType); - var preloadedSceneInstance = await AssetManager.LoadScene(kvp.Value); - - if (preloadedSceneInstance.Scene.IsValid()) + if (!GameFlowManager.Instance.GameFlowSceneMappingSo.FlowToSceneMapping.TryGetValue(gameFlowState, out var assetRef)) { - DeactivateScene(preloadedSceneInstance.Scene); - _loadedSceneDatas.Add(kvp.Key, new SceneData(preloadedSceneInstance.Scene, preloadedSceneInstance)); + Debug.LogError($"[SceneManager] {gameFlowState}의 AssetReference가 없습니다."); + return; } - else + + var runtimeKey = GetRuntimeKey(assetRef); + if (_assetKeyToSceneData.TryGetValue(runtimeKey, out var existing)) { - Debug.LogError($"[SceneManager] {sceneType}의 씬이 존재하지 않습니다."); + _loadedSceneDatas[gameFlowState] = existing; + return; } + + var loadedInstance = await AssetManager.LoadScene(assetRef); + if (!loadedInstance.Scene.IsValid()) + { + Debug.LogError($"[SceneManager] {gameFlowState}의 씬 로딩 실패"); + return; + } + + DeactivateScene(loadedInstance.Scene); + + var data = new SceneData(loadedInstance.Scene, loadedInstance); + _loadedSceneDatas[gameFlowState] = data; + _assetKeyToSceneData[runtimeKey] = data; } public async Task PreloadAll() { - var assetMapping = GameFlowManager.Instance.GameFlowSceneMappingSo.AssetMapping; - foreach (var kvp in assetMapping) + var flowToSceneMapping = GameFlowManager.Instance.GameFlowSceneMappingSo.FlowToSceneMapping; + + foreach (var pair in flowToSceneMapping) { - if (_loadedSceneDatas.ContainsKey(kvp.Key)) continue; - - var preloadedSceneInstance = await AssetManager.LoadScene(kvp.Value); - - if (preloadedSceneInstance.Scene.IsValid()) + if (_loadedSceneDatas.ContainsKey(pair.Key)) continue; + + var runtimeKey = GetRuntimeKey(pair.Value); + if (_assetKeyToSceneData.TryGetValue(runtimeKey, out var existing)) { - DeactivateScene(preloadedSceneInstance.Scene); - _loadedSceneDatas.Add(kvp.Key, new SceneData(preloadedSceneInstance.Scene, preloadedSceneInstance)); + _loadedSceneDatas[pair.Key] = existing; + continue; } - else + + var instance = await AssetManager.LoadScene(pair.Value); + if (!instance.Scene.IsValid()) { - Debug.LogError($"[SceneManager] {kvp.Key}의 씬이 존재하지 않습니다."); + Debug.LogError($"[SceneManager] {pair.Key}의 씬 로딩 실패"); + continue; } + + DeactivateScene(instance.Scene); + var data = new SceneData(instance.Scene, instance); + _loadedSceneDatas[pair.Key] = data; + _assetKeyToSceneData[runtimeKey] = data; } } - public async Task ActivateScene(SceneType sceneType) + public async Task ActivateScene(GameFlowState newFlowState) { - if (_currentSceneType == sceneType) return; + if (!_loadedSceneDatas.TryGetValue(newFlowState, out var sceneData)) + { + Debug.LogError($"[SceneManager] Scene not loaded: {newFlowState}"); + return; + } + + var activeScene = UnityEngine.SceneManagement.SceneManager.GetActiveScene(); + if (sceneData.Scene == activeScene) + { + Debug.Log($"[SceneManager] 이미 활성화된 씬입니다: {newFlowState}"); + return; + } foreach (var handler in _sceneTransitionHandlerSo.Handlers.Where(handler => handler != null)) { - await handler.OnBeforeSceneActivate(sceneType); + await handler.OnBeforeSceneActivate(); } - - if (_loadedSceneDatas.TryGetValue(sceneType, out var sceneData)) - { - foreach (var root in sceneData.Scene.GetRootGameObjects()) - { - root.SetActive(true); - } - if (sceneData.Scene.IsValid()) - { - UnityEngine.SceneManagement.SceneManager.SetActiveScene(sceneData.Scene); - _currentSceneType = sceneType; - } - else - { - Debug.LogError($"[SceneManager] {sceneType}의 Scene이 유효하지 않습니다."); - } + foreach (var root in sceneData.Scene.GetRootGameObjects()) + { + root.SetActive(true); + } + + if (sceneData.Scene.IsValid()) + { + UnityEngine.SceneManagement.SceneManager.SetActiveScene(sceneData.Scene); } else { - Debug.LogError($"[SceneManager] Scene not loaded: {sceneType}"); + Debug.LogError($"[SceneManager] {newFlowState}의 Scene이 유효하지 않습니다."); } - + foreach (var handler in _sceneTransitionHandlerSo.Handlers.Where(handler => handler != null)) { - await handler.OnAfterSceneActivate(sceneType); + await handler.OnAfterSceneActivate(); } } - public void DeactivateScene(SceneType sceneType) + public void DeactivateScene(GameFlowState gameFlowState) { - if (_loadedSceneDatas.TryGetValue(sceneType, out var sceneData)) + if (_loadedSceneDatas.TryGetValue(gameFlowState, out var sceneData)) { - foreach (var root in sceneData.Scene.GetRootGameObjects()) - { - root.SetActive(false); - } + DeactivateScene(sceneData.Scene); } } @@ -178,17 +186,23 @@ private void DeactivateScene(Scene scene) } } - public async Task UnloadSceneBySceneType(SceneType sceneType) + public async Task UnloadScene(GameFlowState gameFlowState) { - if (_loadedSceneDatas.TryGetValue(sceneType, out var sceneData)) + if (_loadedSceneDatas.TryGetValue(gameFlowState, out var sceneData)) { if (sceneData.SceneInstance == null) return; - if (GameFlowManager.Instance.GameFlowSceneMappingSo.AssetMapping.ContainsKey(sceneType)) + if (GameFlowManager.Instance.GameFlowSceneMappingSo.FlowToSceneMapping + .TryGetValue(gameFlowState, out var assetRef)) { - await AssetManager.UnloadScene((SceneInstance)sceneData.SceneInstance); + _assetKeyToSceneData.Remove(GetRuntimeKey(assetRef)); } + + _loadedSceneDatas.Remove(gameFlowState); + await AssetManager.UnloadScene(sceneData.SceneInstance.Value); } } + + private string GetRuntimeKey(AssetReference reference) => reference.RuntimeKey.ToString(); } } \ No newline at end of file diff --git a/Assets/_DDD/_Scripts/GameFramework/Scene/SceneTransitionHandler.cs b/Assets/_DDD/_Scripts/GameFramework/Scene/SceneTransitionHandler.cs index 7dce93b25..82b8575d4 100644 --- a/Assets/_DDD/_Scripts/GameFramework/Scene/SceneTransitionHandler.cs +++ b/Assets/_DDD/_Scripts/GameFramework/Scene/SceneTransitionHandler.cs @@ -5,7 +5,7 @@ namespace DDD { public abstract class SceneTransitionHandler : ScriptableObject { - public abstract Task OnBeforeSceneActivate(SceneType sceneType); - public abstract Task OnAfterSceneActivate(SceneType sceneType); + public abstract Task OnBeforeSceneActivate(); + public abstract Task OnAfterSceneActivate(); } } \ No newline at end of file