异步加载场景
代码以及总结
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class Lesson20 : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
#region 知识点一 回顾场景同步切换
//SceneManager.LoadScene("Lesson20test");
//需要在build settings中添加场景才能使用
//同步切换的缺点:
//1.unity会删除当前场景的所有对象
//2.同时加载下一个场景的相关信息
//3.当前对象过多或者下一个场景对象过多时 会非常耗时并造成卡顿
//对于切换的卡顿 可以用异步切换解决这个问题
#endregion
#region 知识点二 场景异步加载
//1.通过事件回调函数 实现异步加载
//AsyncOperation oa = SceneManager.LoadSceneAsync("Lesson20test");
//当场景异步加载结束后 自动调用事件函数
//如果希望在加载之后做一些说明 可以把逻辑加入到事件中
//oa.completed += (a) =>
//{
// print("加载结束");
//};
//oa.completed += LoadOver;
//2.通过协程异步加载
//加载场景会把当前场景上 没有特殊处理的对象都删除
//所以协程中部分逻辑 可能执行部不了
//解决办法:让处理场景加载的脚本衣服的对象 过场景时 不被移除
// 使用函数 DontDestroyOnLoad(this.gameobject);
DontDestroyOnLoad(this.gameObject);
StartCoroutine(LoadScenes("Lesson20test"));
#endregion
}
private void LoadOver(AsyncOperation ao)
{
print("loadover");
}
IEnumerator LoadScenes(string name)
{
AsyncOperation ao = SceneManager.LoadSceneAsync(name);
//unity内部会发现是异步加载类型的返回对象
//会等待异步加载结束后 才会执行迭代器之后的内容
//协程的好处 是异步加载场景时 可以在加载的同时做一些别的逻辑
print("异步加载中");
//yield return ao;
//print("异步加载后");
//可以在异步加载过程中 更新进度条
//第一种 利用场景异步加载的进度 更新 但不准确 不常用
while(!ao.isDone)
{
print(ao.progress);
yield return null;
}
//离开循环 意味着加载结束 进度套满 完成切换 然后对进度条隐藏
//第二种 根据游戏规则 自己定义 进度条变化的条件
yield return ao;
//场景加载结束 更新20%
//接着加载场景的其他信息 比如加载怪物
//再更新20%
//接着加载场景模型 ……………………
}
}
#region 总结
//场景异步加载 和 资源异步加载 一样
//有两种方式
//1.通过事件回调函数
//2.协程异步加载
//他们的优缺点表现和资源异步加载 也是一样的
//1.事件回调函数
//优点:写法简单,逻辑清晰
//缺点:只能加载完场景做一些事情 不能再加载过程中处理逻辑
//2.协程异步加载
//优点:可以在加载过程中处理逻辑,比如进度条更新等
//缺点:写法较为麻烦,要通过协程
#endregion
写一个异步加载场景的管理器
管理器代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.SceneManagement;
public class SceneMgr
{
private static SceneMgr instance = new SceneMgr();
public static SceneMgr Instance => instance;
private SceneMgr() { }
public void LoadScene(string name,UnityAction action)
{
AsyncOperation ao = SceneManager.LoadSceneAsync(name);
//只是completed加入的委托一定要给予一个参数 此处a并没有用到
ao.completed += (a) =>
{
//通过lamda表达式包裹一层 在内部直接调用外部传入的委托
action();
};
}
}
管理器测试脚本
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Lesson20Test : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
SceneMgr.Instance.LoadScene("Lesson20test", () =>
{
print("加载结束");
});
}
}