using System; using System.IO; using Cysharp.Threading.Tasks; using UnityEngine; using UnityEngine.SceneManagement; using ProjSG.Resource; using YooAsset; public enum StageName { Login, Game, } public class StageManager : Singleton, IManager { public StageName currentStage; public Action AfterLoadingGameScene; public Action BeforeLoadingGameScene; // public Action OnSwitchAccount; private LaunchWinData launchWinData = null; public UniTask Init() { UIManager.Instance.OnCloseWindow += OnCloseWindow; return UniTask.CompletedTask; } public void Release() { AfterLoadingGameScene = null; BeforeLoadingGameScene = null; UIManager.Instance.OnCloseWindow -= OnCloseWindow; } public async UniTaskVoid ToLoginScene() { UIManager.Instance.DestroyAllUI(); // US3: Show loading screen FIRST, then load resources with progress LoadingWin loadingWin = await UIManager.Instance.OpenWindowAsync(); InitLoadingWinData(loadingWin); // Phase 1 (0% ~ 50%): Scene loading if (AssetSource.isUseAssetBundle) { var handle = YooAssetService.Instance.BeginLoadScene("Assets/ResourcesOut/Scenes/Login.unity", LoadSceneMode.Single, LocalPhysicsMode.None, true); while (!handle.IsDone) { if (handle.Progress >= 0.9f) handle.UnSuspend(); loadingWin.SetProgress(handle.Progress * 0.5f); await UniTask.Yield(); } } else { var asyncOp = SceneManager.LoadSceneAsync("Login"); asyncOp.allowSceneActivation = false; while (!asyncOp.isDone) { if (asyncOp.progress >= 0.9f) asyncOp.allowSceneActivation = true; loadingWin.SetProgress(asyncOp.progress * 0.5f); await UniTask.Yield(); } } // Phase 2 (50% ~ 100%): Manager initialization await WaitForManagerProgress(loadingWin, 0.5f, 1.0f, ConfigManager.Instance.GetLoadingProgress, Main.InitManagers); loadingWin.SetProgress(1f, true); await UniTask.Delay(TimeSpan.FromSeconds(0.5f)); loadingWin.CloseWindow(); Main.OnSwitchToLoginScene(); currentStage = StageName.Login; UIManager.Instance.OpenWindowAsync().ContinueWith(s => { UIManager.Instance.OpenWindowAsync().Forget(); DumpLoginSceneDiagnostics("ToLoginScene open triggered").ContinueWith(() => { if (VersionUtility.Instance.NeedDownAsset() && !AssetVersionUtility.hasDownLoadFullAsset) { DownloadHotMgr.Instance.ClearDownloadCache(); InGameDownLoad.Instance.inGameDownLoadAllow = true; InGameDownLoad.Instance.TryDownLoad(InGameDownLoad.Dominant.None); } }).Forget(); }).Forget(); } // 返回登录界面 如断线 public async UniTaskVoid ReturnToLoginScene() { UIManager.Instance.DestroyAllUI(); if (AssetSource.isUseAssetBundle) await YooAssetService.Instance.LoadSceneAsync("Assets/ResourcesOut/Scenes/Login.unity"); else await SceneManager.LoadSceneAsync("Login"); Main.OnSwitchToLoginScene(); currentStage = StageName.Login; UIManager.Instance.OpenWindowAsync().ContinueWith(s => { UIManager.Instance.OpenWindowAsync().Forget(); DumpLoginSceneDiagnostics("ToLoginScene open triggered").ContinueWith(() => { if (ServerForceExitHintWin.reason != 0) { UIManager.Instance.OpenWindowAsync().Forget(); } // SoundPlayer.Instance.StopBackGroundMusic(); SoundPlayer.Instance.PlayLoginMusic(); }).Forget(); }).Forget(); } private async UniTask DumpLoginSceneDiagnostics(string context) { await UniTask.DelayFrame(2); UIManager.Instance.DumpUIDiagnostics(context + " after 2 frames"); await UniTask.DelayFrame(30); UIManager.Instance.DumpUIDiagnostics(context + " after 32 frames"); } protected float GetManagerRequestDataProgress() { if (Main.managers.Count == 0) { return 1f; } int count = 0; for (int i = 0; i < Main.managers.Count; i++) { var manager = Main.managers[i]; if (manager.IsNessaryDataReady()) { count++; } } return ((float)count) / ((float)Main.managers.Count); } public async UniTaskVoid ToGameScene() { UIManager.Instance.DestroyAllUI(); BeforeLoadingGameScene?.Invoke(); // US3: Show loading screen FIRST, then load resources with progress LoadingWin loadingWin = await UIManager.Instance.OpenWindowAsync(); InitLoadingWinData(loadingWin); SoundPlayer.Instance.StopBackGroundMusic(); // Phase 1 (0% ~ 50%): Scene loading if (AssetSource.isUseAssetBundle) { var handle = YooAssetService.Instance.BeginLoadScene("Assets/ResourcesOut/Scenes/Game.unity", LoadSceneMode.Single, LocalPhysicsMode.None, true); while (!handle.IsDone) { if (handle.Progress >= 0.9f) handle.UnSuspend(); loadingWin.SetProgress(handle.Progress * 0.5f); await UniTask.Yield(); } } else { var asyncOp = SceneManager.LoadSceneAsync("Game"); asyncOp.allowSceneActivation = false; while (!asyncOp.isDone) { if (asyncOp.progress >= 0.9f) asyncOp.allowSceneActivation = true; loadingWin.SetProgress(asyncOp.progress * 0.5f); await UniTask.Yield(); } } // Phase 2 (50% ~ 100%): Manager data ready await WaitForManagerProgress(loadingWin, 0.5f, 1.0f, () => (DTC0403_tagPlayerLoginLoadOK.finishedLogin ? .5f : 0f) + GetManagerRequestDataProgress() * .5f); loadingWin.SetProgress(1f, true); await UniTask.Delay(TimeSpan.FromSeconds(0.5f)); loadingWin.CloseWindow(); // 加载初始化数据完成 currentStage = StageName.Game; Main.OnEnterGameScene(); AfterLoadingGameScene?.Invoke(); UIManager.Instance.OpenWindowAsync().Forget(); //游戏内日志关闭 #if !UNITY_EDITOR if (File.Exists(Directory.GetParent(Application.persistentDataPath) + "/Debug") || LocalSave.GetString("#@#BrancH") != string.Empty) { Debug.unityLogger.logEnabled = true; } else { Debug.unityLogger.logEnabled = false; } #endif } protected async UniTask OnLoading(AsyncOperation asyncOperation, Func getLoadingProgress, Func anthorTask = null) { asyncOperation.allowSceneActivation = false; LoadingWin loadingWin = await UIManager.Instance.OpenWindowAsync(); InitLoadingWinData(loadingWin); while (!asyncOperation.isDone) { if (asyncOperation.progress >= 0.9f) { asyncOperation.allowSceneActivation = true; } loadingWin.SetProgress(asyncOperation.progress * 0.5f + getLoadingProgress() * 0.5f); await UniTask.Yield(); } float managerProgress = getLoadingProgress(); while (managerProgress < 1f) { loadingWin.SetProgress(asyncOperation.progress * 0.5f + managerProgress * 0.5f); await UniTask.Yield(); managerProgress = getLoadingProgress(); } if (anthorTask != null) { await anthorTask(); } loadingWin.SetProgress(1f, true); await UniTask.Delay(TimeSpan.FromSeconds(0.5f)); loadingWin.CloseWindow(); } /// /// US3: 等待Manager初始化进度并更新LoadingWin。 /// private async UniTask WaitForManagerProgress(LoadingWin loadingWin, float startPct, float endPct, Func getProgress, Func extraTask = null) { float managerProgress = getProgress(); while (managerProgress < 1f) { loadingWin.SetProgress(startPct + managerProgress * (endPct - startPct)); await UniTask.Yield(); managerProgress = getProgress(); } if (extraTask != null) { await extraTask(); } } /// /// US3: 初始化 LoadingWin 数据(从 LaunchWin 继承背景等)。 /// private void InitLoadingWinData(LoadingWin loadingWin) { LaunchWin launchWin = UIManager.Instance.GetUI(); if (launchWin != null && launchWin.IsActive() && launchWinData == null) { launchWinData = launchWin.GetData(); } if (launchWinData != null) { loadingWin.SetData(launchWinData); launchWinData = null; } } private void OnCloseWindow(UIBase closeUI) { if (closeUI is LaunchWin) { launchWinData = (closeUI as LaunchWin).GetData(); } } }