Unity 异步加载 进度条
当我们进行游戏开发时,时常会进行场景切换,如果下个场景较大,切换时就会出现卡顿现象,甚至看起来像是"死机",非常影响用户体验,我们这时就可以运用异步加载,在界面上显示加载的进度条以提升用户体验,接下来我们就简略聊聊异步加载吧.
我要实现的功能是这样的:首先,第一个场景是一个UI界面,点击"开始加载"按钮进行加载下一场景,场景加载完成后自动跳转,通过文本和进度条显示加载进度,如图:
然后,第二个场景,也就是我们要加载的场景名为"Demo Valley",注意此场景必须加入到unity的build中才行(File->Build Setting):
接下来就该上代码了,如下(此脚本挂于Canvas上):
1 using UnityEngine; 2 using UnityEngine.SceneManagement;//注意引用命名空间 3 using System; 4 using UnityEngine.UI; 5 6 public class LoadScene : MonoBehaviour 7 { 8 Slider slider;//滑动条 9 Text text;//文本 10 Button but;//按钮 11 // 加载进度 12 float loadPro = 0; 13 14 // 用以接受异步加载的返回值 15 AsyncOperation AsyncOp = null; 16 17 void Start() 18 { 19 Debug.Log("开始加载"); 20 21 slider = transform.Find("Slider"). GetComponent<Slider>(); 22 slider.value = 0; 23 text = transform.Find("Text").GetComponent<Text>(); 24 but = transform.Find("Button").GetComponent<Button>(); 25 but.onClick.AddListener(StartLoad);//绑定按钮事件 26 27 } 28 29 //点击按钮,开始加载下一场景,文本和进度条显示加载进度 30 void StartLoad() 31 { 32 AsyncOp = SceneManager.LoadSceneAsync("Demo Valley",LoadSceneMode.Single);//异步加载场景名为"Demo Valley"的场景,LoadSceneMode.Single表示不保留现有场景 33 AsyncOp.allowSceneActivation = false;//allowSceneActivation =true表示场景加载完成后自动跳转,经测,此值默认为true 34 } 35 36 void Update() 37 { 38 if (AsyncOp!=null)//如果已经开始加载 39 { 40 loadPro = AsyncOp.progress; //获取加载进度,此处特别注意:加载场景的progress值最大为0.9!!! 41 } 42 if (loadPro >= 0.9f)//因为progress值最大为0.9,所以我们需要强制将其等于1 43 { 44 loadPro = 1; 45 } 46 slider.value = Mathf.Lerp(slider.value, loadPro,1*Time.deltaTime);//滑动块的value以插值的方式紧跟进度值 47 if (slider.value > 0.99f) 48 { 49 slider.value = 1; 50 AsyncOp.allowSceneActivation = true; 51 } 52 text.text =string.Format("{0:F0}%", slider.value*100);//文本中以百分比的格式显示加载进度 53 } 54 }
此处需要注意的地方有以下几点:
- 加载场景的progress值最大为0.9!!!不知道其用意为何.
- AsyncOp.allowSceneActivation 表示场景加载完成后,是否自动跳转,为true时自动跳转.网上有说当其为false时,场景进度只加载至0.9不再加载,当将其更改为true后,继续加载剩下的0.1,因为没有想出合适的检测方法,所有没有检测真假。
- 本文提到的异步加载本身就是运用的协程进行的加载!网上有些用Coroutine和LoadSceneAsync合用进行的异步加载,不明其意.
- 在实际开发中,进度条的显示有可能会安排在一个新建的过度场景中,原理跟本文的原理相同,无非就是把异步加载的脚本挂在过度场景的Start()函数中而已.
- 此案例中加载场景我们用的SceneManager.LoadSceneAsync()来加载场景,当我们只加载一些预制体时,Resources.LoadAsync()的用法和注意事项与其基本相同.
- 我们之所以在StartLoad函数中将AsyncOp.allowSceneActivation = false,等slider.value > 0.99f时再使其为true,是为了避免UI中进度条还未达到100%时场景已经跳转的情况出现;而使用插值的方式使进度条的值趋近实际的加载进度是为了避免UI中进度条已经达到100%,但是场景还未加载完成的情况出现,也就是说,我们使用插值实际上就是在为场景加载的最后0.1争取时间.