我以为做个进度条很简单,分分钟解决,结果折腾了一天才搞定,Unity有很多坑,要做完美需要逐一解决.
问题1:最简单的方法不能实现100%的进度
用最简单的方法来实现,不能实现100%的进度,原因是Unity加载完新场景立马就激活新场景了,无法显示最后的进度.解决办法就是使用allowSceneActivation来控制进入场景的时机.
问题2:使用allowSceneActivation后进度卡在90%
这个问题官网论坛也有人讨论,解决办法就是自己手动修补最后的10%,
问题3:进度条一顿一顿地增加.不平滑
解决办法手动插值平滑
问题4:www和LoadLevelAsync两部分进度的整合问题
大部分场景是打成Bundle包的,先要WWW加载,再LoadLevelAsync,两部分的进度要整合在一起,
少量场景是不打Bundle包的,比如登录场景,
if (nextSceneID == (int)GlobeEnum.SceneDefine.LOGIN) yield return StartCoroutine(LoadNormalScene(sceneTable.ResName)); else yield return StartCoroutine(LoadBundleScene(sceneTable.ResName));
问题5:用yield return null代替Update()来处理每帧的进度界面更新.
用yield return null来处理更新,比如在Update函数里面处理,代码更简洁,但是要注意一个问题就是while死循环的问题
每个while的地方必须要对应一个yield return null,
经过以上处理,进度条看起来完美了很多,终于能满足我这个完美主义者的要求了. (o_o)
代码如下:
IEnumerator LoadNormalScene(string sceneName, float startPercent = 0) { GameRoot.Instance.CurrentSceneId = (int)LoadingWindow.nextSceneID; loadingText.text = "加载场景中..."; int startProgress = (int)(startPercent * 100); int displayProgress = startProgress; int toProgress = startProgress; AsyncOperation op = Application.LoadLevelAsync(sceneName); op.allowSceneActivation = false; while (op.progress < 0.9f) { toProgress = startProgress + (int)(op.progress * (1.0f - startPercent) * 100); while (displayProgress < toProgress) { ++displayProgress; SetProgress(displayProgress); yield return null; } yield return null; } toProgress = 100; while (displayProgress < toProgress) { ++displayProgress; SetProgress(displayProgress); yield return null; } op.allowSceneActivation = true; } IEnumerator LoadBundleScene(string sceneName) { string path = BundleManager.GetBundleLoadPath(BundleManager.PathSceneData, sceneName + ".data"); WWW www = new WWW(path); loadingText.text = "加载资源包中..."; int displayProgress = 0; int toProgress = 0; while (!www.isDone) { toProgress = (int)(www.progress * m_BundlePercent * 100); while (displayProgress < toProgress) { ++displayProgress; SetProgress(displayProgress); yield return null; } yield return null; } toProgress = (int)(m_BundlePercent * 100); while (displayProgress < toProgress) { ++displayProgress; SetProgress(displayProgress); yield return null; } yield return www; if (null != www.assetBundle) { m_LastSceneBundle = www.assetBundle; yield return StartCoroutine(LoadNormalScene(sceneName, m_BundlePercent)); } } void SetProgress(int progress) { loadingBar.value = progress * 0.01f; loadingProgress.text = progress.ToString() + " %"; }
LoadBundleScene表示加载打包的场景
m_BundlePercent表示加载bundle包占总进度的百分比,默认0.7f