一、异步加载场景的过程
1、异步加载场景用到的API
LoadSceneAsync
2、异步加载的参数说明
- (1)默认参数:SceneManagement.LoadSceneAsync(“SceneName”);
AsyncOperation task = SceneManager.LoadSceneAsync("SceneName");
- (2)异步加载时的两种加载模式-Single和Additive
关于【活动场景】和【非活动场景】有些什么差异,本文不做讨论。
//定义加载任务
AsyncOperation loadTask = SceneManager.LoadSceneAsync("场景2", LoadSceneMode.Additive);
//AsyncOperation loadTask = SceneManager.LoadSceneAsync("场景2", LoadSceneMode.Single);
await loadTask; //实际加载过程
- (3)Single异步加载的流程
AsyncOperation asyncLoad = SceneManager.LoadSceneAsync("SceneName", LoadSceneMode.Single);
加载的步骤解释:
步骤 | 进度值 | 事项描述 |
---|---|---|
第一步 | 0% ~ 90% | 把资源加入到内存中 |
第二步 | 初始化新加入的场景,激活新加入的场景,设置为【活动场景】 | |
第三步 | 新场景激活后,原来的场景会被卸载和清理 | |
第四步 | asyncLoad.isDone设置为true | 当 isDone 属性为 true 时,表示场景切换已完成,新场景已经完全加载并激活,旧场景已经被卸载。 |
加载过程:
- 1、进度值:0%~90% 加载新场景,当到进度值达到90%时,代表场景资源已经加入到内存中,后面10%的时间留给新旧场景的显示切换、新场景初始化、旧场景资源回收。
- 2、场景要如何切换,【自动显示】还是【代码手动控制】它显示
下面是加载完毕自动显示:
AsyncOperation task = SceneManager.LoadSceneAsync("SceneName");
await loadTask;
下面是手工控制场景的显示
//定义加载任务
AsyncOperation loadTask = SceneManager.LoadSceneAsync("SceneName");
loadTask.allowSceneActivation = false; //加载完毕场景不立即显示
await loadTask; //实际加载过程
//此处,用户要进行其他操作,比如点击一个按钮,把数据上传到服务器
//...
loadTask.allowSceneActivation = true; //设置成true后,系统开始后续的10%的工作,会把新场景显示,把老场景卸载
二、大场景切换面临的问题
1、理想情况下的加载
- (1)、先定义一个Progress的对象(进度报告器),相当于一个事件,当进度值有变化的时候,就会回调该方法。
- (2)、异步加载资源,并把Progress对象绑定到加载过程。
// 定义进度报告器
var progress = new Progress<float>(value =>
{
//更新滑动条进度
Debug.Log($"加载进度: {
value * 100}%");
});
//实际加载
await SceneManager.LoadSceneAsync("场景2", LoadSceneMode.Single).ToUniTask(progress: progress);
2、实际加载情况
-
(1)、存在的问题
要加载的是小场景时,进度报告非常丝滑,一点也不卡顿。
但是,让要加载的是大场景的时候,update主线程卡死,进度不会走,一直在0%,等几秒钟之后,加载完毕时,进度突然跳成100%,这就太刺激了。
测试环境说明:Unity2021.3.40 -
(2)、改进方法
把进度条改成加载前、加载中和加载后,真正的加载放在【加载中】。
三、进度条的设计
(1)如何划分进度条
我们把进度条分成三个部分,如下图的阶段一、二、三。
我们把加载的真正过程放在阶段一和阶段二之间,加载时,进度条暂停不动。
为了看起来丝滑一些,我们把进度条设置曲线动画
(2)加载效果
四、如何给进度条配上曲线动画
如何给滑动条设置曲线动画,如下图所示,在1秒内,让滑块从0%跑到33%,跑的时- 候不匀速,而是先快后慢。
(1)曲线运动速度的设置
public class JumpScene : MonoBehaviour
{
/// <summary>
/// 【第一段进度条动画】的动画曲线
/// </summary>
[Header("【第一段进度条动画】的动画曲线")]
public AnimationCurve startAnim;
//......
}
在面板上设置曲线速率
(2)曲线速率与运动的实现:按照给定的曲线速度运动,而不是匀速运动
public async UniTask test4()
{
var progress = 0.0f; //当前累计耗时
var duration = 3f; //给定的动画时间,3秒
var progressCurve = 0f; //曲线进度,按照曲线速度运动,而不是匀速运动
while (true)
{
progress += Time.deltaTime;
progressCurve = startAnim.Evaluate(progress / duration) / duration;
Debug.Log(progressCurve);
if (progress > duration) break;
await UniTask.Yield();
}
}
五、主要代码
(1)过程说明
大场景加载的时候,异步加载的进度值会卡死,因为update主线程卡死了
(无论是协程还是用异步,都没有改观,都是卡死状态)。
出现该情况的时候,进度会卡住,直到加载完毕,进度值突然从【0%】调到【90%】,
90%代表资源加载完毕,余下10%的时间是用来进行场景显示和资源回收处理的。
1、前面三分之一:初始化…
2、…实际加载…
3、中间三分之一:假装在加载…
4、后面三分之一:加载后资源处理…实际加载的时候,资源调入完毕时进度
(2)代码清单
/// <summary>
/// 场景跳转:异步加载一个场景,显示进度条,进度条滑动动画
///
/// **************************************************************************
/// 大场景加载的时候,异步加载的进度值会卡死,因为update主线程卡死了
/// (无论是协程还是用异步,都没有改观,都是卡死状态)。
/// 出现该情况的时候,进度会卡住,直到加载完毕,进度值突然从【0%】调到【90%】,
/// 90%代表资源加载完毕,余下10%的时间是用来进行场景显示和资源回收处理的。
/// 1、前面三分之一:初始化.........
<