using UnityEngine; using System.Collections; using UnityEngine.Events; using UnityEngine.SceneManagement; using System; using Snxxz.UI; using TableConfig; public class StageManager : Singleton { private Stage m_CurrentStage; private Stage.E_StageType m_StageType; public UnityAction onStageLoadFinish; public event Action onStartStageLoadingEvent; public event Action loadingProgressEvent; bool m_IsServerPreparing = false; public bool isServerPreparing { get { return m_IsServerPreparing; } set { m_IsServerPreparing = value; } } public Stage.E_StageType StageType { get { return m_StageType; } } public Stage CurrentStage { get { return m_CurrentStage; } } int m_CurrentMapId; public int currentMapId { get { return m_CurrentMapId; } private set { m_CurrentMapId = value; } } int m_CurrentMapResID; public int currentMapResId { get { return m_CurrentMapResID; } private set { m_CurrentMapResID = value; } } string m_StageAssetName; public string stageAssetName { get { return m_StageAssetName; } } float m_LoadingProgress = 0f; float loadingProgress { get { return m_LoadingProgress; } set { m_LoadingProgress = value; if (loadingProgressEvent != null) { loadingProgressEvent(Mathf.Clamp01(m_LoadingProgress)); } } } public bool isLoading { get; private set; } StageLoadTimeOutCatcher loadTimeOutCatcher; public StageManager() { DebugEx.LogFormat("初始化StageManager"); } public void Load(int stageId) where T : Stage { loadTimeOutCatcher = StageLoadTimeOutCatcher.Begin(stageId); // 读取配置的方式创建场景 var mapResConfig = DTCA127_tagMCStartChangeMap.GetMapResourcesConfig(); if (AssetSource.sceneFromEditor || AssetVersionUtility.unPriorAssetDownLoadDone) { SnxxzGame.Instance.StartCoroutine(LoadCoroutine(stageId, mapResConfig.ID, mapResConfig.MapResources, true)); } else { var assetVersion = AssetVersionUtility.GetAssetVersion(StringUtility.Contact("maps/", mapResConfig.MapResources.ToLower())); if (assetVersion.IsPriorAsset()) { SnxxzGame.Instance.StartCoroutine(LoadCoroutine(stageId, mapResConfig.ID, mapResConfig.MapResources, true)); } else { SnxxzGame.Instance.StartCoroutine(BackToNoviceVillageWhileMapResourceLacked(mapResConfig.ID)); } } } public void LoadCreateRoleStage() { SnxxzGame.Instance.StartCoroutine(LoadCoroutine(2, 0, "CreateRole_001", false)); } public void LoadSelectRoleStage() { SnxxzGame.Instance.StartCoroutine(LoadCoroutine(2, 0, "CreateRole_001", false)); } public void LoadLoginStage() { if (PlayerDatas.Instance.hero != null) { GAMgr.Instance.ServerDie(PlayerDatas.Instance.hero.ServerInstID); GAMgr.Instance.Release(PlayerDatas.Instance.hero); PlayerDatas.Instance.hero = null; } SnxxzGame.Instance.StartCoroutine(LoadCoroutine(1, 0, "Level_Login", false)); } IEnumerator LoadCoroutine(int _stageId, int mapResConfigID, string _resources, bool _needEmpty) where T : Stage { if (currentMapResId != 0 && currentMapResId == mapResConfigID) { #if UNITY_EDITOR Debug.LogFormat("StageManager出现加载相同地图行为:" + mapResConfigID); #endif if (loadTimeOutCatcher != null) { loadTimeOutCatcher.Stop(); loadTimeOutCatcher = null; } ExceptionCatcher.ReportException("场景加载 Step1", StringUtility.Contact("StageManager出现加载相同地图行为:", mapResConfigID)); yield break; } isLoading = true; Application.backgroundLoadingPriority = ThreadPriority.High; try { if (onStartStageLoadingEvent != null) { onStartStageLoadingEvent(currentMapId); } } catch (Exception ex) { Debug.LogError("场景加载开始事件发生异常:" + ex); ExceptionCatcher.ReportException("场景加载 Step2", ex); } var progressBuf = loadingProgress = 0f; var timer = 0f; var duration = 1f; var lastCurrentMapResId = currentMapResId; var lastMapId = currentMapId; currentMapResId = mapResConfigID; currentMapId = _stageId; m_StageAssetName = _resources; SystemSetting.Instance.LetFPSUnLimit(); try { WindowCenter.Instance.asyncLoad.StopAllTasks(); //为什么在这个地方要调用两次关闭其他窗口的接口呢,这个水就深了。 //因为有些界面被关闭的时候,会去打开主界面,所以,还得再关闭一次关闭其他窗口的界面,防止主界面被意外开启。 switch (_stageId) { case 2: WindowCenter.Instance.DestoryWinsByStage(WindowCenter.WindowStage.Login); WindowCenter.Instance.CloseOthers(); if (!WindowCenter.Instance.CheckOpen()) { WindowCenter.Instance.Open(true); } WindowCenter.Instance.CloseOthers(); break; case 1: WindowCenter.Instance.DestoryWinsByStage(WindowCenter.WindowStage.Launch); WindowCenter.Instance.CloseOthers(); if (!WindowCenter.Instance.CheckOpen()) { WindowCenter.Instance.Open(true); } WindowCenter.Instance.CloseOthers(); break; default: WindowCenter.Instance.DestoryWinsByStage(WindowCenter.WindowStage.SelectRole); WindowCenter.Instance.CloseOthers(); if (!WindowCenter.Instance.CheckOpen()) { LoadingWin.targetMapResId = currentMapResId; WindowCenter.Instance.Open(true); } WindowCenter.Instance.CloseOthers(); break; } } catch (System.Exception ex) { ExceptionCatcher.ReportException("场景加载 Step3", ex); } loadingProgress += 0.05f; // 存在当前场景则进行卸载 if (CurrentStage != null) { CurrentStage.UnInitialize(); } //////////////////////////////////////////////////////////////////////////////////////////// // 加载一个空的场景,用以卸载掉之前场景的对象,再加载新的场景,防止2个场景的对象内存占用过多 // 同步加载的方法 if (_needEmpty) { SceneManager.LoadScene("Empty"); } var unloadUnUsedOperation = Resources.UnloadUnusedAssets(); while (!unloadUnUsedOperation.isDone) { yield return null; } loadingProgress += 0.05f; GC.Collect(); loadingProgress += 0.1f; try { if (!AssetSource.sceneFromEditor) { AssetBundleUtility.Instance.UnloadAssetBundle("maps/map000_xsdt", true, false); AssetBundleUtility.Instance.UnloadAssetBundle(GetAssetBundleNameByStageId(lastMapId, lastCurrentMapResId), true, false); AssetBundleUtility.Instance.Sync_LoadAll(GetAssetBundleNameByStageId(currentMapId, currentMapResId)); } } catch (System.Exception ex) { ExceptionCatcher.ReportException("场景加载 Step4", ex); } var sceneLoadOperation = SceneManager.LoadSceneAsync(_resources); progressBuf = loadingProgress; timer = 0f; duration = 1f; while (!sceneLoadOperation.isDone) { timer += Time.deltaTime; loadingProgress = Mathf.Clamp(progressBuf + timer / duration * 0.6f, progressBuf, progressBuf + 0.6f); yield return null; } if (_stageId == 10010) { while (!PreFightMission.Instance.IsHandleMissionState) { yield return null; } try { // 如果用户尚未完成前期战斗部分 if (!PreFightMission.Instance.IsFinished()) { if (!AssetSource.sceneFromEditor) { AssetBundleUtility.Instance.Sync_LoadAll("maps/map000_xsdt"); } SceneManager.LoadScene("Map000_Xsdt", LoadSceneMode.Additive); } } catch (System.Exception ex) { ExceptionCatcher.ReportException("场景加载 Step5", ex); } } yield return null; loadingProgress = loadingProgress + 0.1f; // 场景加载完就可以确定玩家位置了, 不需要等待具体场景的逻辑初始化 if (_stageId > 2) { try { InitHero(); } catch (System.Exception ex) { ExceptionCatcher.ReportException("场景加载 Step6", ex); } } try { GameObject _gameObject = new GameObject(string.Format("__Stage_{0}_", _resources)); m_CurrentStage = _gameObject.AddComponent(); m_StageType = m_CurrentStage is DungeonStage ? Stage.E_StageType.Dungeon : Stage.E_StageType.MainCity; m_CurrentStage.mapId = _stageId; } catch (System.Exception ex) { ExceptionCatcher.ReportException("场景加载 Step7", ex); } yield return null; loadingProgress += 0.1f; // 由于0401包只是通知服务端开始加载地图, 并不表示已经加载完毕 // 客户端由0401开始加载地图, 可能存在客户端加载完毕但是服务端还没准备好的情况 // 所以针对副本地图需要在这里等待服务端0109回包才能发送此包 progressBuf = loadingProgress; timer = 0f; duration = 1f; while (isServerPreparing) { timer += Time.deltaTime; loadingProgress = Mathf.Clamp(progressBuf + timer / duration * 0.2f, progressBuf, progressBuf + 0.2f); yield return null; } if (m_StageType == Stage.E_StageType.Dungeon) { var mapOk = new C0107_tagCInitMapOK(); mapOk.MapID = PlayerDatas.Instance.baseData.MapID; mapOk.Type = 0; GameNetSystem.Instance.SendInfo(mapOk); } else { Debug.LogFormat("不发包0107:当前Stage:{0}", CurrentStage); } isServerPreparing = false; //如果是登录,那么要等待登录过程全部完成 while (m_StageType == Stage.E_StageType.Dungeon && DTC0403_tagPlayerLoginLoadOK.neverLoginOk) { yield return null; } loadingProgress = 1f; try { if (onStageLoadFinish != null) { onStageLoadFinish(); } } catch (Exception ex) { Debug.LogError("场景加载完成事件发生异常:" + ex); ExceptionCatcher.ReportException("场景加载 Step8", ex); } if (loadTimeOutCatcher != null) { loadTimeOutCatcher.Stop(); } loadTimeOutCatcher = null; Application.backgroundLoadingPriority = ThreadPriority.BelowNormal; isLoading = false; DebugEx.LogFormat("StageManager => Load Scene : {0} Finished.", _resources); WindowCenter.Instance.Close(); SystemSetting.Instance.SetGameFps(SystemSetting.Instance.GetGameFps()); } IEnumerator BackToNoviceVillageWhileMapResourceLacked(int _mapResId) { currentMapResId = _mapResId; LoadingWin.targetMapResId = 1; WindowCenter.Instance.Open(true); while (isServerPreparing) { yield return null; } var mapOk = new C0107_tagCInitMapOK(); mapOk.MapID = PlayerDatas.Instance.baseData.MapID; mapOk.Type = 0; GameNetSystem.Instance.SendInfo(mapOk); //如果是登录,那么要等待登录过程全部完成 while (m_StageType == Stage.E_StageType.Dungeon && DTC0403_tagPlayerLoginLoadOK.neverLoginOk) { yield return null; } yield return WaitingForSecondConst.WaitMS1000; var mapConfig = Config.Instance.Get(PlayerDatas.Instance.baseData.MapID); if (mapConfig.MapFBType == (int)MapType.OpenCountry) { var sjzMapConfig = Config.Instance.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(); } if (loadTimeOutCatcher != null) { loadTimeOutCatcher.Stop(); } loadTimeOutCatcher = null; } private void InitHero() { // 初始化摄像机 if (!CameraController.Instance) { UnityEngine.Object.Instantiate(Resources.Load("Prefabs/GameCamera")); CameraController.Instance.AcceptInput = false; CameraController.Instance.CameraObject.enabled = false; } GA_Hero _hero = PlayerDatas.Instance.hero; if (_hero == null) { _hero = GAMgr.Instance.RequestPlayer(PlayerDatas.Instance.PlayerId, E_ActorGroup.User, null); } _hero.State = E_ActorState.Idle; _hero.ActorInfo.ResetHp((int)PlayerDatas.Instance.baseData.HP, -1, (int)PlayerDatas.Instance.baseData.HP); _hero.CalculateMoveSpeed((ushort)PlayerDatas.Instance.extersion.SpeedValue); _hero.CalculateAtkSpeed(PlayerDatas.Instance.extersion.battleValEx1); _hero.InitBornPos(PlayerDatas.Instance.baseData.PosX, PlayerDatas.Instance.baseData.PosY); CameraController.Instance.SetLookTarget(_hero.Root); CameraController.Instance.Apply(); PlayerPackModel _packModel = ModelCenter.Instance.GetModel(); SinglePackModel _equipModel = _packModel.GetSinglePackModel(PackType.rptEquip); byte _suitLevel = 0; ItemModel _itemModel = _equipModel.GetItemModelByIndex((int)RoleEquipType.retClothes); if (_itemModel != null) { if (_itemModel.itemInfo.IsSuite == 1) { _suitLevel = (byte)_itemModel.useDataDict[30][0]; } _hero.SwitchClothes((uint)_itemModel.itemInfo.ItemID); _hero.ChangeEquip((int)RoleEquipType.retClothes, (uint)_itemModel.itemInfo.ItemID, _suitLevel); } else { _hero.SwitchClothes(0); } _itemModel = _equipModel.GetItemModelByIndex((int)RoleEquipType.retWeapon); if (_itemModel != null) { _hero.SwitchWeapon((uint)_itemModel.itemInfo.ItemID); } else { _hero.SwitchWeapon(0); } _itemModel = _equipModel.GetItemModelByIndex((int)RoleEquipType.retWeapon2); if (_itemModel != null) { _hero.SwitchSecondary((uint)_itemModel.itemInfo.ItemID); } else { _hero.SwitchSecondary(0); } _itemModel = _equipModel.GetItemModelByIndex((int)RoleEquipType.retWing); if (_itemModel != null) { _hero.SwitchWing((uint)_itemModel.itemInfo.ItemID); } _itemModel = _equipModel.GetItemModelByIndex((int)RoleEquipType.mount); if (_itemModel != null) { PlayerMountDatas _mountModel = ModelCenter.Instance.GetModel(); if (_mountModel.HorseRidingBool) { _hero.OnHorse(1); } } _itemModel = _equipModel.GetItemModelByIndex((int)RoleEquipType.retSpiritAnimal); if (_itemModel != null) { _hero.SwitchGuard((uint)_itemModel.itemInfo.ItemID); } _itemModel = _equipModel.GetItemModelByIndex((int)RoleEquipType.retHat); if (_itemModel != null) { if (_itemModel.itemInfo.IsSuite == 1) { _suitLevel = (byte)_itemModel.useDataDict[30][0]; _hero.ChangeEquip((int)RoleEquipType.retHat, (uint)_itemModel.itemInfo.ItemID, _suitLevel); } } _itemModel = _equipModel.GetItemModelByIndex((int)RoleEquipType.retBelt); if (_itemModel != null) { if (_itemModel.itemInfo.IsSuite == 1) { _suitLevel = (byte)_itemModel.useDataDict[30][0]; _hero.ChangeEquip((int)RoleEquipType.retBelt, (uint)_itemModel.itemInfo.ItemID, _suitLevel); } } _itemModel = _equipModel.GetItemModelByIndex((int)RoleEquipType.retShoes); if (_itemModel != null) { if (_itemModel.itemInfo.IsSuite == 1) { _suitLevel = (byte)_itemModel.useDataDict[30][0]; _hero.ChangeEquip((int)RoleEquipType.retShoes, (uint)_itemModel.itemInfo.ItemID, _suitLevel); } } _itemModel = _equipModel.GetItemModelByIndex((int)RoleEquipType.retTrousers); if (_itemModel != null) { if (_itemModel.itemInfo.IsSuite == 1) { _suitLevel = (byte)_itemModel.useDataDict[30][0]; _hero.ChangeEquip((int)RoleEquipType.retTrousers, (uint)_itemModel.itemInfo.ItemID, _suitLevel); } } _hero.IdleImmediate(); _hero.SetFairyLeagueHeadUp(PlayerDatas.Instance.baseData.MapID == FairyLeagueModel.FAIRY_LEAGUE_DUNGEON); // 判断buff if (StatusMgr.Instance.IsExist(PlayerDatas.Instance.PlayerId, StatusMgr.Instance.redNameBuffID)) { _hero.SwitchRedName(true); } _hero.RequestLight(); PlayerDatas.Instance.hero = _hero; } private string GetAssetBundleNameByStageId(int stageID, int mapResID) { switch (stageID) { case 0: return string.Empty; case 1: return "maps/level_login"; case 2: return "maps/createrole_001"; default: var mapResConfig = Config.Instance.Get(mapResID); if (mapResConfig != null) { return StringUtility.Contact("maps/", mapResConfig.MapResources); } return string.Empty; } } }