如何用Unity加载一个真实的进度条

本文探讨了Unity游戏加载过程中存在的问题及优化方法,通过在异步加载前加入`WaitForEndOfFrame()`,实现了加载画面与资源加载的分离,显著改善了加载过程中的用户体验,减少了白屏现象。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

实际上就是MOMO贴出来的方法其实是有问题的,用过的才知道。至于别的几乎不用找,根本一个抄一个,抄来抄去都是一样,没自己的东西。


用过MOMO那个方法的都应该会发现了,当进度条开始显示的时候,基本上已经加载到80%了,可能也跟Unity版本有关,我的是4.3.4 。但是实际上Unity的工作原理差不多就那样,在Start里面直接开始加载的协程,实际上一开始就会阻塞,导致画面刚刚渲染出来的时候,已经完成了一部分的加载,而很多资源会在一开始就加载了,如果这里的资源太多了,那么就会像我一样,显示很长时间的白屏,肯定加载画面出来的时候,进度已到80%,而且剩余的20%花费时间很短,一闪就过去了。


那么要怎么解决这个问题呢,其实做过同步加载的人都知道,要选渲染加载画面再加载,Unity自称异步加载,实际上还是同步,了解协程的都知道,那个东西和线程半毛钱关系没有,依然是个同步方法。不知道Unity何时才能提供真正的多线程加载支持,这种加载方式感觉越来越不入流了。


不喜欢看废话的,直接跳过上面看修改后的代码

实际上就是只加上一句yield return new WaitForEndOfFrame();


[csharp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. using UnityEngine;  
  2. using System.Collections;  
  3.   
  4. public class Loading : MonoBehaviour {  
  5.   
  6.     private float fps = 10.0f;  
  7.     private float time;  
  8.     //一组动画的贴图,在编辑器中赋值。  
  9.     public Texture2D[] animations;  
  10.     private int nowFram;  
  11.     //异步对象  
  12.     AsyncOperation async;  
  13.   
  14.     //读取场景的进度,它的取值范围在0 - 1 之间。  
  15.     int progress = 0;  
  16.   
  17.     void Start()  
  18.     {  
  19.         //在这里开启一个异步任务,  
  20.         //进入loadScene方法。  
  21.         StartCoroutine(loadScene());  
  22.     }  
  23.   
  24.     //注意这里返回值一定是 IEnumerator  
  25.     IEnumerator loadScene()  
  26.     {  
  27.         yield return new WaitForEndOfFrame();//<strong>加上这么一句就可以先显示加载画面然后再进行加载</strong>  
  28.         async = Application.LoadLevelAsync(Globe.loadName);  
  29.   
  30.         //读取完毕后返回, 系统会自动进入C场景  
  31.         yield return async;  
  32.   
  33.     }  
  34.   
  35.     void OnGUI()  
  36.     {  
  37.         //因为在异步读取场景,  
  38.         //所以这里我们可以刷新UI  
  39.         DrawAnimation(animations);  
  40.   
  41.     }  
  42.   
  43.     void Update()  
  44.     {  
  45.   
  46.         //在这里计算读取的进度,  
  47.         //progress 的取值范围在0.1 - 1之间, 但是它不会等于1  
  48.         //也就是说progress可能是0.9的时候就直接进入新场景了  
  49.         //所以在写进度条的时候需要注意一下。  
  50.         //为了计算百分比 所以直接乘以100即可  
  51.         progress =  (int)(async.progress *100);  
  52.   
  53.         //有了读取进度的数值,大家可以自行制作进度条啦。  
  54.         Debug.Log("xuanyusong" +progress);  
  55.   
  56.     }  
  57.     //这是一个简单绘制2D动画的方法,没什么好说的。  
  58.     void   DrawAnimation(Texture2D[] tex)  
  59.     {  
  60.   
  61.         time += Time.deltaTime;  
  62.   
  63.          if(time >= 1.0 / fps){  
  64.   
  65.              nowFram++;  
  66.   
  67.              time = 0;  
  68.   
  69.              if(nowFram >= tex.Length)  
  70.              {  
  71.                 nowFram = 0;  
  72.              }  
  73.         }  
  74.         GUI.DrawTexture(new Rect( 100,100,40,60) ,tex[nowFram] );  
  75.   
  76.         //在这里显示读取的进度。  
  77.         GUI.Label(new Rect( 100,180,300,60), "lOADING!!!!!" + progress);  
  78.   
  79.     }  
  80.   
  81. }  

实际上即使这样的加载也是非常有问题的,那就是资源会集中在一起加载,也就是刚开始加载到百分之几,然后卡住相当长的时间,然后突然到80%左右。解决这个问题估计只能用把资源都分包的方法了,这个还在研究中。

不过有趣的是,如果直接使用Unity自带的资源包,第一次虽然会慢点,但是只要加载过一次,即使你关闭了游戏,再次打开就基本上无需加载,虽然这样就失去了加密的保护。但现在下结论为时过早,说不定即使加密分包,也可以做到这样,虽然不知道这个是什么机制,但是我感觉还是不太可能。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值