//场景加载结束:后续资源准备(预加载等) //注意:这里使用协程,子类别重写了,需要加载的资源添加到列表就可以了 public static async ETTask OnPrepare(this SceneLoadComponent self, Action <float> progress_callback) { for (int i = 0; i < self.Total; i++) { switch (self.Types[i]) { case SceneLoadComponent.LoadType.Image: self.PreLoadTask.Add(self.StartPreloadImage(self.Paths[i])); break; case SceneLoadComponent.LoadType.Material: self.PreLoadTask.Add(self.StartPreloadMaterial(self.Paths[i])); break; case SceneLoadComponent.LoadType.GameObject: self.PreLoadTask.Add(self.StartPreloadGameObject(self.Paths[i], self.ObjCount[self.Paths[i]])); break; default: break; } } self.ProgressCallback = progress_callback; if (self.Total <= 0) { return; } await ETTaskHelper.WaitAll(self.PreLoadTask); }
//预加载材质 public static void AddPreloadMaterial(this SceneLoadComponent self, string path) { if (self.Paths.Contains(path)) { return; } self.Paths.Add(path); self.Types.Add(SceneLoadComponent.LoadType.Material); self.Total++; }
//预加载图集 private static ETTask StartPreloadImage(this SceneLoadComponent self, string path) { ETTask task = ETTask.Create(); ImageLoaderComponent.Instance.LoadImageAsync(path, (go) => { self.FinishCount++; self.ProgressCallback?.Invoke((float)self.FinishCount / self.Total); task.SetResult(); }).Coroutine(); return(task); }
//预加载prefab private static ETTask StartPreloadGameObject(this SceneLoadComponent self, string path, int count) { ETTask task = ETTask.Create(); GameObjectPoolComponent.Instance.PreLoadGameObjectAsync(path, count, () => { self.FinishCount++; self.ProgressCallback?.Invoke((float)self.FinishCount / self.Total); task.SetResult(); }).Coroutine(); return(task); }
//预加载prefab public static void AddPreloadGameObject(this SceneLoadComponent self, string path, int count) { if (self.ObjCount.ContainsKey(path)) { self.ObjCount[path]++; return; } self.ObjCount.Add(path, count); self.Paths.Add(path); self.Types.Add(SceneLoadComponent.LoadType.GameObject); self.Total++; }
//切换场景 async static ETTask InnerSwitchScene(this SceneManagerComponent self, SceneConfig scene_config, bool needclean = false, SceneLoadComponent slc = null) { float slid_value = 0; Game.EventSystem.Publish(new UIEventType.LoadingProgress { Progress = slid_value }); CameraManagerComponent.Instance.SetCameraStackAtLoadingStart(); //等待资源管理器加载任务结束,否则很多Unity版本在切场景时会有异常,甚至在真机上crash Log.Info("InnerSwitchScene ProsessRunning Done "); while (ResourcesComponent.Instance.IsProsessRunning()) { await TimerComponent.Instance.WaitAsync(1); } slid_value += 0.01f; Game.EventSystem.Publish(new UIEventType.LoadingProgress { Progress = slid_value }); await TimerComponent.Instance.WaitAsync(1); //清理UI Log.Info("InnerSwitchScene Clean UI"); await UIManagerComponent.Instance.DestroyWindowExceptNames(self.DestroyWindowExceptNames.ToArray()); slid_value += 0.01f; Game.EventSystem.Publish(new UIEventType.LoadingProgress { Progress = slid_value }); //清除ImageLoaderManager里的资源缓存 这里考虑到我们是单场景 Log.Info("InnerSwitchScene ImageLoaderManager Cleanup"); ImageLoaderComponent.Instance.Clear(); //清除预设以及其创建出来的gameobject, 这里不能清除loading的资源 Log.Info("InnerSwitchScene GameObjectPool Cleanup"); if (needclean) { GameObjectPoolComponent.Instance.Cleanup(true, self.ScenesChangeIgnoreClean); slid_value += 0.01f; Game.EventSystem.Publish(new UIEventType.LoadingProgress { Progress = slid_value }); //清除除loading外的资源缓存 List <UnityEngine.Object> gos = new List <UnityEngine.Object>(); for (int i = 0; i < self.ScenesChangeIgnoreClean.Count; i++) { var path = self.ScenesChangeIgnoreClean[i]; var go = GameObjectPoolComponent.Instance.GetCachedGoWithPath(path); if (go != null) { gos.Add(go); } } Log.Info("InnerSwitchScene ResourcesManager ClearAssetsCache excludeAssetLen = " + gos.Count); ResourcesComponent.Instance.ClearAssetsCache(gos.ToArray()); slid_value += 0.01f; Game.EventSystem.Publish(new UIEventType.LoadingProgress { Progress = slid_value }); } else { slid_value += 0.02f; Game.EventSystem.Publish(new UIEventType.LoadingProgress { Progress = slid_value }); } await ResourcesComponent.Instance.LoadSceneAsync(self.GetSceneConfigByName(SceneNames.Loading).SceneAddress, false); Log.Info("LoadSceneAsync Over"); slid_value += 0.01f; Game.EventSystem.Publish(new UIEventType.LoadingProgress { Progress = slid_value }); //GC:交替重复2次,清干净一点 GC.Collect(); GC.Collect(); var res = Resources.UnloadUnusedAssets(); while (!res.isDone) { await TimerComponent.Instance.WaitAsync(1); } slid_value += 0.12f; Game.EventSystem.Publish(new UIEventType.LoadingProgress { Progress = slid_value }); Log.Info("异步加载目标场景 Start"); //异步加载目标场景 await ResourcesComponent.Instance.LoadSceneAsync(scene_config.SceneAddress, false); slid_value += 0.65f; Game.EventSystem.Publish(new UIEventType.LoadingProgress { Progress = slid_value }); //准备工作:预加载资源等 if (slc != null) { await slc.OnPrepare((progress) => { Game.EventSystem.Publish(new UIEventType.LoadingProgress { Progress = slid_value + 0.15f * progress }); if (progress > 1) { Log.Error("scene load waht's the f**k!"); } }); } slid_value += 0.15f; Game.EventSystem.Publish(new UIEventType.LoadingProgress { Progress = slid_value }); CameraManagerComponent.Instance.SetCameraStackAtLoadingDone(); self.CurrentScene = scene_config.Name; slid_value = 1; Game.EventSystem.Publish(new UIEventType.LoadingProgress { Progress = slid_value }); //等久点,跳的太快 await TimerComponent.Instance.WaitAsync(500); }
//切换场景 public static async ETTask SwitchScene(this SceneManagerComponent self, string scene_name, bool needclean = false, SceneLoadComponent slc = null) { if (self.Busing) { return; } var scene_config = self.GetSceneConfigByName(scene_name); if (scene_config == null) { return; } if (self.CurrentScene == scene_config.Name) { return; } self.Busing = true; //打开loading界面 Log.Info("InnerSwitchScene start open uiloading"); await Game.EventSystem.PublishAsync(new UIEventType.LoadingBegin()); await self.InnerSwitchScene(scene_config, needclean, slc); //加载完成,关闭loading界面 await Game.EventSystem.PublishAsync(new UIEventType.LoadingFinish()); //释放loading界面引用的资源 GameObjectPoolComponent.Instance.CleanupWithPathArray(true, self.ScenesChangeIgnoreClean); self.Busing = false; }
/// <summary> /// 切换到某个场景 /// </summary> /// <param name="name"></param> public static async ETTask ChangeToScene(this AOISceneViewComponent self, string name = null, SceneLoadComponent slc = null) { if (string.IsNullOrEmpty(name) && string.IsNullOrEmpty(self.CurMap)) { return; } if (SceneManagerComponent.Instance.Busing) { return; } SceneManagerComponent.Instance.Busing = true; self.LastGridX = null; self.LastGridY = null; Log.Info("InnerSwitchScene start open uiloading"); //打开loading界面 await Game.EventSystem.PublishAsync(new UIEventType.LoadingBegin()); float slid_value = 0; if (name != self.CurMap)//需要重新加载场景物体 { Game.EventSystem.Publish(new UIEventType.LoadingProgress { Progress = slid_value }); if (SceneManagerComponent.Instance.CurrentScene != SceneNames.Map) { CameraManagerComponent.Instance.SetCameraStackAtLoadingStart(); } slid_value = 0.1f; Game.EventSystem.Publish(new UIEventType.LoadingProgress { Progress = slid_value }); //等待资源管理器加载任务结束,否则很多Unity版本在切场景时会有异常,甚至在真机上crash Log.Info("InnerSwitchScene ProsessRunning Done "); while (ResourcesComponent.Instance.IsProsessRunning()) { await TimerComponent.Instance.WaitAsync(1); } //清理旧场景 foreach (var item in self.DynamicSceneObjectMapObj) { if (item.Value.IsLoading) { item.Value.IsLoading = false; } else { GameObjectPoolComponent.Instance.RecycleGameObject(item.Value.Obj); } } self.DynamicSceneObjectMapObj.Clear(); self.DynamicSceneObjectMapCount.Clear(); slid_value = 0.2f; Game.EventSystem.Publish(new UIEventType.LoadingProgress { Progress = slid_value }); if (SceneManagerComponent.Instance.CurrentScene != SceneNames.Map) { //清理UI Log.Info("InnerSwitchScene Clean UI"); await UIManagerComponent.Instance.DestroyWindowExceptNames(SceneManagerComponent.Instance.DestroyWindowExceptNames.ToArray()); slid_value = 0.25f; Game.EventSystem.Publish(new UIEventType.LoadingProgress { Progress = slid_value }); //清除ImageLoaderManager里的资源缓存 这里考虑到我们是单场景 Log.Info("InnerSwitchScene ImageLoaderManager Cleanup"); ImageLoaderComponent.Instance.Clear(); //清除预设以及其创建出来的gameobject, 这里不能清除loading的资源 Log.Info("InnerSwitchScene GameObjectPool Cleanup"); GameObjectPoolComponent.Instance.Cleanup(true, SceneManagerComponent.Instance.ScenesChangeIgnoreClean); slid_value = 0.3f; Game.EventSystem.Publish(new UIEventType.LoadingProgress { Progress = slid_value }); //清除除loading外的资源缓存 List <UnityEngine.Object> gos = new List <UnityEngine.Object>(); for (int i = 0; i < SceneManagerComponent.Instance.ScenesChangeIgnoreClean.Count; i++) { var path = SceneManagerComponent.Instance.ScenesChangeIgnoreClean[i]; var go = GameObjectPoolComponent.Instance.GetCachedGoWithPath(path); if (go != null) { gos.Add(go); } } Log.Info("InnerSwitchScene ResourcesManager ClearAssetsCache excludeAssetLen = " + gos.Count); ResourcesComponent.Instance.ClearAssetsCache(gos.ToArray()); slid_value = 0.45f; Game.EventSystem.Publish(new UIEventType.LoadingProgress { Progress = slid_value }); await ResourcesComponent.Instance.LoadSceneAsync(SceneManagerComponent.Instance.GetSceneConfigByName(SceneNames.Loading).SceneAddress, false); Log.Info("LoadSceneAsync Over"); slid_value = 0.5f; Game.EventSystem.Publish(new UIEventType.LoadingProgress { Progress = slid_value }); //GC:交替重复2次,清干净一点 GC.Collect(); GC.Collect(); var res = Resources.UnloadUnusedAssets(); while (!res.isDone) { await TimerComponent.Instance.WaitAsync(1); } slid_value = 0.6f; Game.EventSystem.Publish(new UIEventType.LoadingProgress { Progress = slid_value }); Log.Info("异步加载目标场景 Start"); var scene_config = SceneManagerComponent.Instance.GetSceneConfigByName(SceneNames.Map); //固定Map空场景 //异步加载目标场景 await ResourcesComponent.Instance.LoadSceneAsync(scene_config.SceneAddress, false); SceneManagerComponent.Instance.CurrentScene = scene_config.Name; } slid_value = 0.7f; Game.EventSystem.Publish(new UIEventType.LoadingProgress { Progress = slid_value }); //准备工作:预加载资源等 if (slc != null) { await slc.OnPrepare((progress) => { Game.EventSystem.Publish(new UIEventType.LoadingProgress { Progress = slid_value + 0.3f * progress }); if (progress > 1) { Log.Error("scene load waht's the f**k!"); } }); } slid_value = 1f; Game.EventSystem.Publish(new UIEventType.LoadingProgress { Progress = slid_value }); CameraManagerComponent.Instance.SetCameraStackAtLoadingDone(); } Game.EventSystem.Publish(new UIEventType.LoadingProgress { Progress = 1 }); //等久点,跳的太快 await TimerComponent.Instance.WaitAsync(100); //加载完成,关闭loading界面 await Game.EventSystem.PublishAsync(new UIEventType.LoadingFinish()); SceneManagerComponent.Instance.Busing = false; self.CurMap = name; }