using Snxxz.UI; using System; using System.Collections.Generic; using UnityEngine; using UnityEngine.SceneManagement; public class StageLoadProcessor : MonoBehaviour { float progressBuf = 0.1f; public float progress { get; private set; } StageLoadTask currentTask = null; Queue tasks = new Queue(); public void Begin(Queue tasks) { this.tasks = tasks; var totalWeight = 0f; foreach (var task in tasks) { totalWeight += task.exceptedWeight; } foreach (var task in tasks) { task.weight = task.exceptedWeight / totalWeight; } } public void Complete(int mapId, int lineId) { StageLoad.Instance.ReportComplete(mapId, lineId); } private void Update() { if (currentTask == null) { if (tasks.Count > 0) { currentTask = tasks.Dequeue(); currentTask.Begin(); } } if (currentTask != null) { currentTask.Update(); if (!currentTask.done) { progress = Mathf.Clamp01(progressBuf + currentTask.weight * currentTask.progress); } else { progressBuf += currentTask.weight; currentTask.End(); if (tasks.Count == 0) { Complete(currentTask.command.toMapId, currentTask.command.toLineId); } currentTask = null; } } } public abstract class StageLoadTask { public float timer { get; protected set; } public float duration { get; protected set; } public bool done { get; protected set; } public float progress { get; protected set; } public float exceptedWeight { get; protected set; } public float weight { get; set; } public readonly StageLoad.StageLoadCommand command; public StageLoadTask(StageLoad.StageLoadCommand command) { this.command = command; } public abstract void Begin(); public abstract void Update(); public abstract void End(); } public class WaitConfigInitedTask : StageLoadTask { public WaitConfigInitedTask(StageLoad.StageLoadCommand command) : base(command) { } public override void Begin() { exceptedWeight = 0.2f; done = ConfigInitiator.done; } public override void End() { } public override void Update() { timer += Time.deltaTime; done = ConfigInitiator.done; } } public class PreProcessTask : StageLoadTask { public PreProcessTask(StageLoad.StageLoadCommand command) : base(command) { exceptedWeight = 0.1f; } public override void Begin() { SystemSetting.Instance.LetFPSUnLimit(); Application.backgroundLoadingPriority = ThreadPriority.High; StageLoad.Instance.BroadcastStageLoadStartEvent(command.fromMapId); try { switch (command.toMapId) { case 1: case 2: case 3: if (PlayerDatas.Instance.hero != null) { PlayerDatas.Instance.hero.Behaviour.StopHandupAI(true); GAMgr.Instance.Release(PlayerDatas.Instance.hero); PlayerDatas.Instance.hero = null; } break; default: break; } } catch (System.Exception ex) { Debug.LogError(ex); } try { //为什么在这个地方要调用两次关闭其他窗口的接口呢,这个水就深了。 //因为有些界面被关闭的时候,会去打开主界面,所以,还得再关闭一次关闭其他窗口的界面,防止主界面被意外开启。 WindowCenter.Instance.asyncLoad.StopAllTasks(); switch (command.toMapId) { case 2: case 3: WindowCenter.Instance.DestoryWinsByStage(WindowCenter.WindowStage.Login); WindowCenter.Instance.CloseOthers(); if (!WindowCenter.Instance.IsOpen()) { WindowCenter.Instance.Open(true); } break; case 1: WindowCenter.Instance.DestoryWinsByStage(WindowCenter.WindowStage.Launch); WindowCenter.Instance.CloseOthers(); if (!WindowCenter.Instance.IsOpen()) { WindowCenter.Instance.Open(true); } break; default: WindowCenter.Instance.DestoryWinsByStage(WindowCenter.WindowStage.SelectRole); WindowCenter.Instance.CloseOthers(); if (!WindowCenter.Instance.IsOpen()) { var dataMapId = MapUtility.GetDataMapId(command.toMapId); var lineId = MapUtility.GetLineId(command.toMapId, command.toLineId); var config = MapResourcesConfig.GetConfig(dataMapId, lineId); LoadingWin.targetMapResId = config.ID; WindowCenter.Instance.Open(true); } break; } } catch (System.Exception ex) { Debug.LogError(ex); ExceptionCatcher.ReportException("场景加载 Step3", ex); } done = true; } public override void End() { } public override void Update() { } } public class LoadEmptyTask : StageLoadTask { public LoadEmptyTask(StageLoad.StageLoadCommand command) : base(command) { exceptedWeight = 0.2f; } public override void Begin() { duration = 0.2f; SceneManager.LoadScene("Empty"); } public override void End() { } public override void Update() { timer += Time.deltaTime; if (timer > duration) { done = true; progress = timer / duration; } } } public class UnLoadAndGCTask : StageLoadTask { AsyncOperation unloadUnUsedOperation; public UnLoadAndGCTask(StageLoad.StageLoadCommand command) : base(command) { exceptedWeight = 0.2f; } public override void Begin() { if (StageLoad.Instance.currentStage != null) { StageLoad.Instance.currentStage.UnInitialize(); } unloadUnUsedOperation = Resources.UnloadUnusedAssets(); if (command.isClientLoadMap && command.serverType == ServerType.CrossSever) { var sendInfo = new CA108_tagCMRefreshMainServerRole(); GameNetSystem.Instance.SendInfo(sendInfo); } } public override void End() { if (!AssetSource.sceneFromEditor) { AssetBundleUtility.Instance.UnloadAssetBundle("maps/map000_xsdt", true, false); var lastMapId = command.fromMapId; var lastLineId = command.fromLineId; var assetBundleName = GetAssetBundleNameByMapId(lastMapId, lastLineId); if (!string.IsNullOrEmpty(assetBundleName)) { AssetBundleUtility.Instance.UnloadAssetBundle(assetBundleName, true, false); } } GC.Collect(); } public override void Update() { timer += Time.deltaTime; if (unloadUnUsedOperation != null) { done = unloadUnUsedOperation.isDone; progress = unloadUnUsedOperation.progress; } else { done = true; progress = 1f; } } } public class LoadNewSceneTask : StageLoadTask { AsyncOperation operation; public LoadNewSceneTask(StageLoad.StageLoadCommand command) : base(command) { exceptedWeight = 0.4f; } public override void Begin() { var mapId = command.toMapId; var lineId = command.toLineId; if (!AssetSource.sceneFromEditor) { var assetBundleName = GetAssetBundleNameByMapId(mapId, lineId); AssetBundleUtility.Instance.Sync_LoadAll(assetBundleName); } switch (command.toMapId) { case 1: operation = SceneManager.LoadSceneAsync("Level_Login"); break; case 2: case 3: operation = SceneManager.LoadSceneAsync("CreateRole_001"); break; default: var dataMapId = MapUtility.GetDataMapId(mapId); var config = MapResourcesConfig.GetConfig(dataMapId, lineId); operation = SceneManager.LoadSceneAsync(config.MapResources); break; } WindowCenter.Instance.asyncLoad.StopAllTasks(); switch (command.toMapId) { case 1: case 2: case 3: WindowCenter.Instance.CloseOthers(); break; default: WindowCenter.Instance.CloseOthers(); break; } } public override void End() { var mapId = command.toMapId; var lineId = command.toLineId; var levelName = string.Empty; switch (mapId) { case 1: levelName = "__Stage_Level_Login_"; break; case 2: case 3: levelName = "__Stage_CreateRole_001_"; break; default: try { StageLoad.Instance.InitHero(); } catch (Exception ex) { ExceptionCatcher.ReportException("场景加载 InitHero 执行到: " + StageLoad.Instance.initHeroStep, ex); } var dataMapId = MapUtility.GetDataMapId(mapId); var config = MapResourcesConfig.GetConfig(dataMapId, lineId); levelName = string.Format("__Stage_{0}_", config.MapResources); break; } var stageGameObject = new GameObject(levelName); Stage stage; switch (mapId) { case 1: stage = stageGameObject.AddComponent(); break; case 2: stage = stageGameObject.AddComponent(); break; case 3: stage = stageGameObject.AddComponent(); break; case ClientCrossServerOneVsOne.mapId: stage = stageGameObject.AddComponent(); break; case 31250: stage = stageGameObject.AddComponent(); break; case RuneTowerModel.RUNETOWER_MAPID: stage = stageGameObject.AddComponent(); break; case JadeDynastyTowerModel.DATA_MAPID: stage = stageGameObject.AddComponent(); break; case DemonJarModel.DEMONJAR_SINGLEMAPID: stage = stageGameObject.AddComponent(); break; default: stage = stageGameObject.AddComponent(); break; } stage.mapId = mapId; StageLoad.Instance.currentStage = stage; } public override void Update() { timer += Time.deltaTime; if (operation != null) { done = operation.isDone; progress = operation.progress; } else { done = true; progress = 1f; } } } public class Wait0109Task : StageLoadTask { public Wait0109Task(StageLoad.StageLoadCommand command) : base(command) { exceptedWeight = 0.1f; } public override void Begin() { duration = 1f; } public override void End() { var mapOk = new C0107_tagCInitMapOK(); mapOk.MapID = (ushort)command.toMapId; mapOk.Type = 0; StageLoadTimeOutCatcher.RecordProtocol(command.serverType, "0107", DateTime.Now); switch (command.serverType) { case ServerType.Main: GameNetSystem.Instance.SendInfo(mapOk); break; case ServerType.CrossSever: GameNetSystem.Instance.SendToCrossServer(mapOk); break; default: break; } } public override void Update() { timer += Time.deltaTime; if (!command.serverFlag0109) { done = false; progress = timer / duration; } else { done = true; progress = 1f; } } } public class WaitLoginCompleteTask : StageLoadTask { public WaitLoginCompleteTask(StageLoad.StageLoadCommand command) : base(command) { exceptedWeight = 0.2f; } public override void Begin() { duration = 2f; } public override void End() { } public override void Update() { timer += Time.deltaTime; if (DTC0403_tagPlayerLoginLoadOK.neverLoginOk) { done = false; progress = timer / duration; } else { done = true; progress = 1f; } } } public class PostProcessTask : StageLoadTask { public PostProcessTask(StageLoad.StageLoadCommand command) : base(command) { exceptedWeight = 0.1f; } public override void Begin() { StageLoad.Instance.BroadcastStageLoadEndEvent(); WindowCenter.Instance.Close(); SystemSetting.Instance.SetGameFps(SystemSetting.Instance.GetGameFps()); GAMgr.Instance.DoReAdjustPos(); GAMgr.Instance.ClearReJustActor(); done = true; } public override void End() { Application.backgroundLoadingPriority = ThreadPriority.BelowNormal; DebugEx.LogFormat("StageLoad => Load Scene : {0} Finished.", command.toMapId); } public override void Update() { } } public class WaitSecondsTask : StageLoadTask { public WaitSecondsTask(StageLoad.StageLoadCommand command, float seconds) : base(command) { duration = seconds; } public override void Begin() { } public override void End() { } public override void Update() { timer += Time.deltaTime; if (timer > duration) { done = true; } else { done = false; progress = timer / duration; } } } public class ReturnToNoviceVillageTask : StageLoadTask { public ReturnToNoviceVillageTask(StageLoad.StageLoadCommand command) : base(command) { } public override void Begin() { if (CrossServerUtility.IsCrossServer()) { var sendInfo = new CC003_tagCGForceQuitCrossState(); GameNetSystem.Instance.SendInfo(sendInfo); } else { var mapConfig = MapConfig.Get(PlayerDatas.Instance.baseData.MapID); if (mapConfig.MapFBType == (int)MapType.OpenCountry) { var sjzMapConfig = MapConfig.Get(10010); var position = new Vector3(sjzMapConfig.BornPoints[0].x, 0, sjzMapConfig.BornPoints[0].y); MapTransferUtility.Send_WorldTransfer(10010, position, MapTransferType.WorldTransport, 255, 0); } else { ModelCenter.Instance.GetModel().ExitCurrentDungeon(); } } done = true; } public override void End() { } public override void Update() { } } private static string GetAssetBundleNameByMapId(int mapId, int lineId) { switch (mapId) { case 0: return string.Empty; case 1: return "maps/level_login"; case 2: case 3: return "maps/createrole_001"; default: var dataMapId = MapUtility.GetDataMapId(mapId); var config = MapResourcesConfig.GetConfig(dataMapId, lineId); if (config != null) { return StringUtility.Contact("maps/", config.MapResources); } else { return string.Empty; } } } }