背景
一般体量的游戏都会有多个场景,其中主场景资源会相对较多,假如使用直接加载的方式加载主场景,就会出现卡顿的现象,这对玩家来说不是好的体验.由此加载该类场景最好使用异步加载,通过异步加载给出加载进度提示,优化场景过渡的体验.
先上效果
可以看出来,异步加载提示进度,同步加载直接卡在哪里.
上代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
public class LoadAsyncScene : MonoBehaviour
{
//异步操作对象
private AsyncOperation asyncOperation;
[Tooltip("加载进度文本")]
public Text progress;
[Tooltip("加载进度数值")]
float progressValue = 0;
[Tooltip("加载进度条图片")]
public Image progressBar;
[Tooltip("下个场景的名字")]
public string Scene_name;
private void Start()
{
Invoke("AsyLoad", 0.1f);//延后0.1秒执行异步,必须的
// AsyLoad();//直接异步会有问题
}
void AsyLoad()
{
StartCoroutine("LoadScene", Scene_name); // 开启协程
}
/// <summary>
/// 通过协程加载场景
/// </summary>
/// <param name="Scene_name">加载的场景名称</param>
/// <returns></returns>
IEnumerator LoadScene(string Scene_name)
{
asyncOperation = SceneManager.LoadSceneAsync(Scene_name);//异步跳转到Scene_name场景
asyncOperation.allowSceneActivation = false;//当game场景加载到90%时,不让它直接跳转到game场景。
yield return asyncOperation;
}
void Update()
{
if (asyncOperation == null) { return; }
progressValue = asyncOperation.progress;
if (asyncOperation.progress >= 0.9f)
{
//值最大为0.9
progressValue = 1.0f;
}
//为滑动条赋值
if (progressValue != progressBar.fillAmount)//进度条的值还没到给定值
{
progressBar.fillAmount = Mathf.Lerp(progressBar.fillAmount, progressValue, Time.deltaTime*2);//不断往前加载,插值加载
if (Mathf.Abs(progressBar.fillAmount - progressValue) < 0.01f)//进度条和给定值很接近了
{
progressBar.fillAmount = progressValue;
}
}
progress.text = ((int)(progressBar.fillAmount * 100)).ToString() + "%";
if ((int)(progressBar.fillAmount * 100) == 100)//进度条到了100%才允许跳
{
//允许异步加载完毕后自动切换场景
// if (Input.anyKeyDown)
asyncOperation.allowSceneActivation = true;
}
}
}
分析
1.异步加载执行需要注意时机
Invoke(“AsyLoad”, 0.1f);//延后0.1秒执行异步,必须的
,这个延后时间,可以浮动, 但不可直接在Start中开启,如果直接开启会出现很多问题.哪些问题呢?
①进度条不正常显示
②跳转的场景不受asyncOperation.allowSceneActivation = false;的控制
这不是我们想看到的,所有,异步加载一定要延后一点点执行.
2. 注意返回异步操作对象
在 IEnumerator 中使用yield return asyncOperation;返回该异步对象,外界通过asyncOperation的相关参数来执行进度.
3.加载显示值需要做处理
progressBar.fillAmount该值是表示异步场景加载进度值得,但是它不是真正的异步,在当前线程里,也是每一帧才能收到一次progressBar.fillAmount传过来的值,所以progressBar.fillAmount的值,很大可能是跳跃的不连续的.当前这一帧得到值为0.03,下一帧就到了0.25,这之间跨度很大,如果我们的进度条显示数据直接从progressBar.fillAmount来,那进度条呈现的状态也会是一卡一卡的.所以我们做进度条显示的数值是先经过处理的, progressBar.fillAmount = Mathf.Lerp(progressBar.fillAmount, progressValue, Time.deltaTime*2);//不断往前加载,插值加载
使用插值是个不错的方法.
4.通过属性值来控制是否能自动跳转到下一场景
asyncOperation.allowSceneActivation = false;//当game场景加载到90%时,不让它直接跳转到game场景。
当 asyncOperation.allowSceneActivation = false时,asyncOperation.progress的值最多加载到0.9,就会停下,如果不做其他操作,场景就会停在这里,无法跳转,想要跳转,就得把asyncOperation.allowSceneActivation =true; 这样场景才能自动跳转.
5.让asyncOperation.allowSceneActivation =true的时机
注意asyncOperation.allowSceneActivation =true可不是任何时候都行,这样能避免 进度条显示还未到100%就跳转的现象,应该等到进度条达到100%再赋值为 true;
if ((int)(progressBar.fillAmount * 100) == 100)//进度条到了100%才允许跳
{
//允许异步加载完毕后自动切换场景
// if (Input.anyKeyDown)
asyncOperation.allowSceneActivation = true;
}