Unity3D手游开发日记(3) - 场景加载进度条的完美方案

时间:2023-03-09 23:09:42
Unity3D手游开发日记(3) - 场景加载进度条的完美方案

我以为做个进度条很简单,分分钟解决,结果折腾了一天才搞定,Unity有很多坑,要做完美需要逐一解决.

问题1:最简单的方法不能实现100%的进度

用最简单的方法来实现,不能实现100%的进度,原因是Unity加载完新场景立马就激活新场景了,无法显示最后的进度.解决办法就是使用allowSceneActivation来控制进入场景的时机.

问题2:使用allowSceneActivation后进度卡在90%

这个问题官网论坛也有人讨论,解决办法就是自己手动修补最后的10%,

问题3:进度条一顿一顿地增加.不平滑

解决办法手动插值平滑

问题4:www和LoadLevelAsync两部分进度的整合问题

大部分场景是打成Bundle包的,先要WWW加载,再LoadLevelAsync,两部分的进度要整合在一起,

少量场景是不打Bundle包的,比如登录场景,

  1. if (nextSceneID == (int)GlobeEnum.SceneDefine.LOGIN)
  2. yield return StartCoroutine(LoadNormalScene(sceneTable.ResName));
  3. else
  4. yield return StartCoroutine(LoadBundleScene(sceneTable.ResName));

问题5:用yield return null代替Update()来处理每帧的进度界面更新.

用yield return null来处理更新,比如在Update函数里面处理,代码更简洁,但是要注意一个问题就是while死循环的问题

每个while的地方必须要对应一个yield return null,

经过以上处理,进度条看起来完美了很多,终于能满足我这个完美主义者的要求了. (o_o)

代码如下:

  1. IEnumerator LoadNormalScene(string sceneName, float startPercent = 0)
  2. {
  3. GameRoot.Instance.CurrentSceneId = (int)LoadingWindow.nextSceneID;
  4. loadingText.text = "加载场景中...";
  5. int startProgress = (int)(startPercent * 100);
  6. int displayProgress = startProgress;
  7. int toProgress = startProgress;
  8. AsyncOperation op = Application.LoadLevelAsync(sceneName);
  9. op.allowSceneActivation = false;
  10. while (op.progress < 0.9f)
  11. {
  12. toProgress = startProgress + (int)(op.progress * (1.0f - startPercent) * 100);
  13. while (displayProgress < toProgress)
  14. {
  15. ++displayProgress;
  16. SetProgress(displayProgress);
  17. yield return null;
  18. }
  19. yield return null;
  20. }
  21. toProgress = 100;
  22. while (displayProgress < toProgress)
  23. {
  24. ++displayProgress;
  25. SetProgress(displayProgress);
  26. yield return null;
  27. }
  28. op.allowSceneActivation = true;
  29. }
  30. IEnumerator LoadBundleScene(string sceneName)
  31. {
  32. string path = BundleManager.GetBundleLoadPath(BundleManager.PathSceneData, sceneName + ".data");
  33. WWW www = new WWW(path);
  34. loadingText.text = "加载资源包中...";
  35. int displayProgress = 0;
  36. int toProgress = 0;
  37. while (!www.isDone)
  38. {
  39. toProgress = (int)(www.progress * m_BundlePercent * 100);
  40. while (displayProgress < toProgress)
  41. {
  42. ++displayProgress;
  43. SetProgress(displayProgress);
  44. yield return null;
  45. }
  46. yield return null;
  47. }
  48. toProgress = (int)(m_BundlePercent * 100);
  49. while (displayProgress < toProgress)
  50. {
  51. ++displayProgress;
  52. SetProgress(displayProgress);
  53. yield return null;
  54. }
  55. yield return www;
  56. if (null != www.assetBundle)
  57. {
  58. m_LastSceneBundle = www.assetBundle;
  59. yield return StartCoroutine(LoadNormalScene(sceneName, m_BundlePercent));
  60. }
  61. }
  62. void SetProgress(int progress)
  63. {
  64. loadingBar.value = progress * 0.01f;
  65. loadingProgress.text = progress.ToString() + " %";
  66. }

LoadNoramlScene表示加载没有打包的场景

LoadBundleScene表示加载打包的场景

m_BundlePercent表示加载bundle包占总进度的百分比,默认0.7f