using UnityEngine; using System; using System.Collections; using Thousandto.Core.Base; using Thousandto.Core.Asset; using Thousandto.Code.Center; using Thousandto.Cfg.Data; using Thousandto.Core.Support; using UnityEngine.SceneManagement; using PathUtils = UnityEngine.Gonbest.MagicCube.PathUtils; using CoroutinePool = UnityEngine.Gonbest.MagicCube.CoroutinePool; using StringUtils = UnityEngine.Gonbest.MagicCube.StringUtils; using FLogger = UnityEngine.Gonbest.MagicCube.FLogger; namespace Thousandto.Code.Logic { /// /// 场景加载类 /// public class SceneLoadingState : GameStateBase { #region//当前变量 //状态转换控制设置 private LoadingState _loadingState = LoadingState.DEFAULT; //加载参数 private LoadingArgs _loadingArgs = null; //目标场景 private GameScene _targetScene = null; #endregion #region//属性信息 public GameScene TaregetScene { get { return _targetScene; } } #endregion #region//构造函数 public SceneLoadingState(GameStateId id) : base(id) { } #endregion protected override GameStateId OnGetStateID() { return GameStateId.SceneLoading; } protected override void OnEnter() { _loadingState = LoadingState.DEFAULT; FrameMonitor.EndProfile(); //FLogger.LogError("Start Loading:"+Time.realtimeSinceStartup); if (HardwareManager.MemoryInfo != null) FLogger.LogTime(string.Format("SceneLoadingState Enter:AppUsed:{0},Free:{1}", HardwareManager.MemoryInfo.GetAppUsedMemory(), HardwareManager.MemoryInfo.GetFreeMemory())); //0做输入检查,以及一些预处理 FLogger.DebugAssert(Arg != null, "SceneLoading OnEnter Arg is NULL"); _loadingArgs = Arg as LoadingArgs; FLogger.DebugAssert(_loadingArgs != null, "SceneLoading Load param is invalid"); FLogger.DebugAssert(_loadingArgs.MapSetting != null, "SceneLoading MapSetting param is invalid"); if (_loadingArgs == null && _loadingArgs.MapSetting == null) { return; } //这里有判定的原因是,在选择界面和创建界面,根据玩家的一些基础信息已经对持久化资源进行了设置 if (_loadingArgs.FrontMapID != 0) { //设置一些不被清除的资源 -- 并且这里的时LocalPlayer也有可能还没有 GameCenter.GameSceneSystem.SetImmortalInfo(true); } //清除场景中的关联的预制 GameCenter.GameSceneSystem.SceneSweepPrefab(); //清除场景远近处理缓存 GameCenter.SceneRestoreSystem.ClearCache(); //只有窗体加载之后才会设置下一个场景 GameCenter.LuaSystem.Adaptor.OpenLoadingForm(() => { //3.开始加载下一个场景的信息 _loadingState = LoadingState.CheckedUpdate; }); } protected override void OnLeave() { //_loadingArgs = null; _loadingState = LoadingState.DEFAULT; IGameState nextState = GameCenter.GameStateSystem.GetNextState(); if (nextState != null) { var next = nextState as GameStateBase; if (next != null) { // 当登出或者重新登录时释放 IGameState state = GameCenter.GameStateSystem.GetCurState(); if (state != null) { if (next.GameStateID == GameStateId.Login || next.GameStateID == GameStateId.AppUpdateCheck) { FLogger.LogTime("OnLeave Next State" + next.GameStateID); //1.处理声音 //2.处理UI //3.发送退出游戏的消息 //4.释放数据 GameCenter.GameSceneSystem.StopBGMusic(); ReleaseData(); } } } } } protected override bool OnUpdate(float deltaTime) { //计时器更新 GameCenter.TimerEventSystem.Update(deltaTime); switch (_loadingState) { case LoadingState.CheckedUpdate: //判断更新 CheckUpdate(); break; case LoadingState.StartImmortalPreLoad: //开始对持久资源进行预加载处理 ResourcesEx.IsPreLoadState = true; if (_loadingArgs.FrontMapID <= 0) { _loadingState = LoadingState.ImmortalPreLoading; FLogger.LogTime("ImmortalPreLoading"); //只有选择或创建角色后才会预加载 GameCenter.ImmortalResSystem.StartPreLoadImmort(); } _loadingState = LoadingState.StartScenePreLoad; break; case LoadingState.ImmortalPreLoading: //正在进行对持久资源进行预加载 if (Time.frameCount % 30 == 0) { ImmortalLoading(); } break; case LoadingState.StartScenePreLoad: //开始场景的预加载处理 ResourcesEx.IsPreLoadState = false; StartScenePreLoad(); break; case LoadingState.EndLoading: //加载完毕 _loadingState = LoadingState.DEFAULT; break; } return true; } #region//判断更新 //判断是否进行分段更新 private void CheckUpdate() { //if (PathUtils.IsStreaming()) //{ // FLogger.LogTime("CheckUpdate"); // //绝对路径,如果不存在,则做分段更新操作 // string filePath = PathUtils.GetStreamingRootPath("/Assets/GameAssets/Resources/Scene/" + _loadingArgs.MapSetting.LevelName + ".unity3d"); // if (!System.IO.File.Exists(filePath) ) // { // UnityEngine.Debug.LogWarning("场景文件不存在,需要更新: " + filePath); // _loadingState = LoadingState.CheckedUpdateWait; // GameCenter.MsgPromptSystem.ShowMsgBox(DeclareMessageString.Get(DeclareMessageString.C_SCENE_LOADING_UPDATE_RES), // DeclareMessageString.Get(DeclareMessageString.C_MSGBOX_CANCEL), // DeclareMessageString.Get(DeclareMessageString.C_MSGBOX_OK), // (_ret) => // { // _loadingState = LoadingState.DEFAULT; // if (_ret == MsgBoxResultCode.Button2) // { // GameCenter.GameSceneSystem.ReturnToUpdate(); // } // else // { // GameCenter.GameSceneSystem.ReturnToLogin(); // } // } // ); // } //} //切换为加载状态 if (_loadingState == LoadingState.CheckedUpdate) { _loadingState = LoadingState.StartImmortalPreLoad; } } //持久资源加载中 private void ImmortalLoading() { var sum = GameCenter.ImmortalResSystem.GetPreLoadSum(); if (sum == 0) { _loadingState = LoadingState.StartScenePreLoad; } else { var cur = GameCenter.ImmortalResSystem.GetPreLoadCurrentCount(); if (cur <= 0) { _loadingState = LoadingState.StartScenePreLoad; } else { GameCenter.LuaSystem.Adaptor.SetLoadingFormProgress(0.5f * ((float)cur / (float)sum)); } } } //开始场景加载中 private void StartScenePreLoad() { FLogger.LogTime("StartScenePreLoad"); GameCenter.LuaSystem.Adaptor.SetLoadingFormProgress(0.5f); _loadingState = LoadingState.ScenePreLoading; //开始切换音乐 GameCenter.GameSceneSystem.PlayBGMusic(_loadingArgs.MapSetting.MapId); //添加后台更新支持 GameCenter.UpdateSystem.CheckSceneResExist(_loadingArgs.MapSetting.MapId, () => { //开始加载场景 SceneRootAssetsLoader.LoadSceneAssets( _loadingArgs.MapSetting.LevelName, () => { bool isLoadFail = ResourcesEx.DebugUIModel ? true : false; if (!SceneRootAssetsLoader.CurrSceneBundleExit()) { //场景下载失败了 isLoadFail = true; } //场景加载完毕 _loadingState = LoadingState.ScenePreLoaded; CoroutinePool.AddTask( LoadWorldAsync( _loadingArgs.MapSetting.MapId, _loadingArgs.MapSetting.Name, _loadingArgs.MapSetting.LevelName, _loadingArgs.MapSetting.CameraName, _loadingArgs.MapSetting.CameraNameNight, _loadingArgs.LineID,_loadingArgs.Position, isLoadFail)); }); }, () => { GameCenter.GameSceneSystem.ReturnToLogin(); }); } private void BackToDefaultMap(bool tologin) { int backMapId = 102599; if (tologin) { //返回的是同一张地图 直接返回登录 GameCenter.GameStateSystem.ChangeState((int)GameStateId.RetToLogin, 1); } else { NetHandler.SendMessage_TransportWorldMap(backMapId, 0); } } #endregion #region 场景读取 IEnumerator LoadBaseScene(String name, String levelName) { //加载一个中间场景// 清除上一个场景数据 FLogger.LogTime("LoadOffScene!"); SceneManager.LoadScene(AssetConstDefine.SceneOffName); //GameCenter.LuaSystem.Adaptor.SetLoadingFormProgress(0.5f); FLogger.LogTime("LoadLevel! : " + levelName); yield return new WaitForEndOfFrame(); // 加载目标场景 SceneManager.LoadScene(levelName); yield return new WaitForEndOfFrame(); SceneRootAssetsLoader.ReleaseSceneBundle(); } // 加载场景 IEnumerator LoadWorldAsync(int id, string name, string levelName, string dayCameraName, string nightCameraName, int lineID, Vector2? position = null, bool isFail = false) { try { GameCenter.LuaSystem.Adaptor.SetLoadingFormProgress(0.9f); FLogger.LogTime("Start LoadWorldAsync!"); _loadingState = LoadingState.Loading; yield return new WaitForEndOfFrame(); //1.开始加载进行物理场景的切换 if (isFail) { //直接加载一个空场景 FLogger.LogTime("LoadEmptyScene!"); SceneManager.LoadScene(AssetConstDefine.SceneEmptyName); yield return new WaitForEndOfFrame(); FLogger.LogTime("空场景加载完成!"); } else { //1.1加载一个中间场景// 清除上一个场景数据 FLogger.LogTime("LoadOffScene!"); SceneManager.LoadScene(AssetConstDefine.SceneOffName); //yield return SceneManager.LoadSceneAsync(AssetConstDefine.SceneOffName, LoadSceneMode.Single); yield return new WaitForEndOfFrame(); //1.2加载目标场景 float testTime = Time.realtimeSinceStartup; FLogger.LogTime("LoadLevel! : " + levelName); var option = SceneManager.LoadSceneAsync(levelName, LoadSceneMode.Single); if (option == null) { //加载空场景 SceneManager.LoadScene(AssetConstDefine.SceneEmptyName); yield return new WaitForEndOfFrame(); FLogger.LogTime("空场景加载完成!"); } else { while (!option.isDone && option.progress < 1) { yield return new WaitForEndOfFrame(); } FLogger.LogTime("场景异步加载完成! : " + levelName); } //SceneManager.LoadScene(levelName); } //1.3删除场景的bundle SceneRootAssetsLoader.ReleaseSceneBundle(); yield return new WaitForEndOfFrame(); //2.物理场景切换成功后,开始创建逻辑场景 FLogger.LogTime("Create Logic Scene"); //Debug.LogError(string.Format("加载场景花费的时间{0}", Time.realtimeSinceStartup - testTime)); _targetScene = new GameScene(); //加载场景的一些逻辑数据信息--寻路等. FLogger.LogTime("LoadSingleMapInfo!"); GameCenter.PathFinderSystem.LoadSingleMapInfo(DeclareMapsetting.Get(id)); FLogger.LogTime("LoadSingleMapInfo Finish!"); _targetScene.Load(id, name, levelName, dayCameraName, nightCameraName, false, false); _targetScene.LineID = lineID; _targetScene.FrontMapID = _loadingArgs.FrontMapID; FLogger.LogTime("LogicScene Is Created!"); //加载玩家周围区域物件资源 FLogger.LogTime("Init SceneRestoreSystem !"); if(_targetScene.GetUnitySceneRoot() != null) GameCenter.SceneRestoreSystem.InitSceneData(_targetScene.GetUnitySceneRoot().gameObject, position); FLogger.LogTime("SceneRestoreSystem Init Finish !"); yield return new WaitForEndOfFrame(); //3.加载玩家自己的数据 //这里需要判断,如果角色玩家数据为空,表示是第一次登陆游戏 //否则,需要重新加载玩家数据, if (LocalPlayerRoot.LocalPlayer != null) { _targetScene.ReloadLocalPlayer(_loadingArgs.Position); } yield return new WaitForEndOfFrame(); FLogger.LogTime("ChangeToState GameStateId.World"); if (_targetScene != null) { _targetScene.TransType = _loadingArgs.transType; _targetScene.TransParam = _loadingArgs.transParam; } //OwnerGameCase.ChangeToState(GameStateId.World, _targetScene); // 直接进入world state GameCenter.GameStateSystem.ChangeState((int)GameStateId.World, _targetScene); } finally { _targetScene = null; //恢复网络数据处理, 恢复心跳 //发送一个进入地图成功的消息给服务端 FLogger.LogTime("Client EnteredMap! finally"); } yield return new WaitForEndOfFrame(); FLogger.LogTime("Client EnteredMap!"); _loadingState = LoadingState.EndLoading; } // 删除已加载数据 -- 断线等状态强制转换 private void ReleaseData() { try { if (_targetScene != null) { _targetScene.Unload(); _targetScene = null; } GameCenter.GameSceneSystem.SceneSweepPrefab(); GameCenter.GameSceneSystem.SceneSweepAsset(); } catch (System.Exception ex) { FLogger.LogException(ex); } } #endregion } }