文章目录
- 一、场景基本操作
- 1、加载切换场景
- 2、获取场景信息
- 3、激活场景
- 4、场景基本属性获取
- 5、已加载场景个数
- 6、获取场景中所有物体
- 7、创建新场景
- 8、卸载销毁场景
- 二、使用协程方法来异步加载场景
- 1、AsyncOperation相关的代码应写在一个协同程序中。
- 2、allowSceneActivation加载完场景是否自动跳转
- 3、progress异步加载的进度
- 4、isDone异步加载是否完成
- 5、priority设置异步操作的优先级
- 6、completed异步加载完成会执行一次这个事件
- 7、简单案例
- 三、封装场景管理器
- 1、同步加载当前场景、下一个场景、上一个场景
- 2、异步切换场景
- 3、异步加载场景获取加载进度条
- 4、完整代码
- 完结
一、场景基本操作
1、加载切换场景
载索引为1的场景
SceneManager.LoadScene(1);
加载名为MyScene的场景
SceneManager.LoadScene("MyScene");
加载场景,LoadSceneMode.Single表示:销毁当前场景,加载要需要的场景,默认
SceneManager.LoadScene("MyScene", LoadSceneMode.Single);
叠加式加载场景,AddSceneMode.Additive表示:当前场景不销毁,并加载需要的场景
SceneManager.LoadScene("MyScene", LoadSceneMode.Additive);
2、获取场景信息
根据场景的名称(在此例中为 “Scene2”)来获取对应的场景对象
Scene scene2 = SceneManager.GetSceneByName("Scene2");
根据指定的场景索引获取场景信息
int sceneIndex = 1; // 假设我们要获取索引为 1 的场景
Scene scene = SceneManager.GetSceneByBuildIndex(sceneIndex);
3、激活场景
设置scene2为当前活动场景
SceneManager.SetActiveScene(scene2);
获取当前激活场景
Scene scene = SceneManager.GetActiveScene();
4、场景基本属性获取
场景名称
Debug.Log(scene.name);
场景是否已经加载
Debug.Log(scene.isLoaded);
场景路径
Debug.Log(scene.path);
场景索引
Debug.Log(scene.buildIndex);
获取当前构建设置中场景的数量。具体来说,它返回在 Unity 的构建设置(Build Settings)窗口中列出的所有场景的总数。
int totalScenes = SceneManager.sceneCountInBuildSettings;
5、已加载场景个数
Debug.Log(SceneManager.sceneCount);
6、获取场景中所有物体
隐藏的根游戏对象也会包含在其中,DontDestroyOnLoad的游戏对象不包含在其中。
GameObject[] gos = scene.GetRootGameObjects();
Debug.Log(gos.Length);
7、创建新场景
Scene newScene = SceneManager.CreateScene("newScene");
8、卸载销毁场景
//本方法不会卸载内存中的场景资源,如果要释放资源,应在调用这个方法后,再调用Resources.UnloadUnusedAssets()
SceneManager.UnloadSceneAsync(newScene);
//用于释放未使用的资源,以帮助管理内存。它会清理那些不再被使用的资源
Resources.UnloadUnusedAssets()
二、使用协程方法来异步加载场景
1、AsyncOperation相关的代码应写在一个协同程序中。
# 开始加载场景
AsyncOperation asyncOperation = SceneManager.LoadSceneAsync("Scene1", LoadSceneMode.Single);
2、allowSceneActivation加载完场景是否自动跳转
值为false表示即使加载场景完毕也不会激活该场景,直到用代码再次把这个变量的值改为true,才会激活该场景。
//加载完场景不要自动跳转
asyncOperation.allowSceneActivation = false;
3、progress异步加载的进度
返回float型,范围是0-1。表示异步加载的进度,开始是0,完成时是1
注意:当AsyncOperation型变量.allowSceneActivation的值为false,这个参数的值最多会卡在0.9,直到AsyncOperation型变量.allowSceneActivation的值变为true,这个参数的值才会变为1
asyncOperation.progress
4、isDone异步加载是否完成
返回bool型。表示该异步加载是否完成。如果完成,则值为true,如果未完成,则值为false。
当AsyncOperation型对象.progress的值为1时,此时这个变量的值才为true,但这样就会激活新的新场景,一般很难观测到AsyncOperation型对象.isDone是true
asyncOperation.isDone
5、priority设置异步操作的优先级
返回int型,用于设置异步操作的优先级。
当有多个异步操作排队时,将优先执行更高优先级的异步操作。但如果异步操作在后台线程上启动, 则更改优先级没有任何效果。
asyncOperation.priority
6、completed异步加载完成会执行一次这个事件
这个是一个有一个AsyncOperation型参数的Action事件。该AsyncOperation型参数存储了本次异步加载的信息。
当异步加载完成,也就是AsyncOperation型对象.isDone的值为true时,会执行一次这个事件。
asyncOperation.completed += Completed()
Action<AsyncOperation> Completed(){
return null;
}
7、简单案例
using UnityEngine;
using UnityEngine.SceneManagement;
public class AsyncTest:MonoBehaviour
{
AsyncOperation asyncOperation;
void Start()
{
StartCoroutine(loadScene());
}
//协程方法用来异步加载场景
IEnumerator loadScene()
{
//异步加载索引为1的场景
operation = SceneManager.LoadSceneAsync(1);
//加载完场景不要自动跳转
operation.allowSceneActivation = false;
//等待资源加载完毕
yield return operation;
}
float timer = 0;
void Update()
{
//输出加载进度 0-0.9,可以按这个值制作加载进度条
Debug.Log(operation.progress);
timer += Time.deltaTime;
//如果到达5秒,再跳转场景
if(timer > 5){
operation.allowSceneActivation = true;
}
}
}
三、封装场景管理器
1、同步加载当前场景、下一个场景、上一个场景
using UnityEngine;
using UnityEngine.SceneManagement;
/// <summary>
/// 场景切换管理器
/// </summary>
public class LoadSceneManager : SingletonPatternBase<LoadSceneManager>
{
/// <summary>
/// 重新切换到当前场景
/// </summary>
public void LoadActiveScene()
{
SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);
}
/// <summary>
/// 切换到下一个场景
/// </summary>
/// <param name="isCyclical">是否循环切换</param>
public void LoadNextScene(bool isCyclical = false)
{
int buildIndex = SceneManager.GetActiveScene().buildIndex + 1;
if (buildIndex > SceneManager.sceneCountInBuildSettings - 1)
{
if (isCyclical)
{
buildIndex = 0;
}
else
{
Debug.LogWarning($"加载场景失败!要加载的场景的索引是{buildIndex}, 越界了!");
return;
}
}
SceneManager.LoadScene(buildIndex);
}
/// <summary>
/// 切换到上一个场景
/// </summary>
/// <param name="isCyclical">是否循环切换</param>
public void LoadPreviousScene(bool isCyclical = false)
{
int buildIndex = SceneManager.GetActiveScene().buildIndex - 1;
if (buildIndex < 0)
{
if (isCyclical)
{
buildIndex = SceneManager.sceneCountInBuildSettings - 1;
}
else
{
Debug.LogWarning($"加载场景失败!要加载的场景的索引是{buildIndex}, 索引不能为负数!");
return;
}
}
SceneManager.LoadScene(buildIndex);
}
}
测试调用
LoadSceneManager.Instance.LoadActiveScene();
LoadSceneManager.Instance.LoadNextScene();
LoadSceneManager.Instance.LoadPreviousScene();
2、异步切换场景
/// <summary>
/// 异步加载场景
/// </summary>
public void LoadSceneAsync(string sceneName, UnityAction completed = null, LoadSceneMode mode = LoadSceneMode.Single)
{
MonoManager.Instance.StartCoroutine(LoadSceneCoroutine(sceneName, completed, mode));
}
private IEnumerator LoadSceneCoroutine(string sceneName, UnityAction completed = null, LoadSceneMode mode = LoadSceneMode.Single)
{
// 开始加载场景
AsyncOperation asyncOperation = SceneManager.LoadSceneAsync(sceneName, mode);
// 等待资源加载完毕
while (!asyncOperation.isDone)
{
yield return null; // 等待下一帧
}
// 加载资源完毕后执行的逻辑
completed?.Invoke();
}
/// <summary>
/// 异步加载场景(通过索引)
/// </summary>
public void LoadSceneAsync(int sceneIndex, UnityAction completed = null, LoadSceneMode mode = LoadSceneMode.Single)
{
MonoManager.Instance.StartCoroutine(LoadSceneCoroutine(sceneIndex, completed, mode));
}
private IEnumerator LoadSceneCoroutine(int sceneIndex, UnityAction completed = null, LoadSceneMode mode = LoadSceneMode.Single)
{
// 开始加载场景
AsyncOperation asyncOperation = SceneManager.LoadSceneAsync(sceneIndex, mode);
// 等待资源加载完毕
while (!asyncOperation.isDone)
{
yield return null; // 等待下一帧
}
// 加载资源完毕后执行的逻辑
completed?.Invoke();
}
测试调用
LoadSceneManager.Instance.LoadSceneAsync(1);
LoadSceneManager.Instance.LoadSceneAsync("Scene1");
3、异步加载场景获取加载进度条
public void LoadSceneAsync(string sceneName, UnityAction<float> loading = null, UnityAction<AsyncOperation> completed = null, bool setActiveAfterCompleted = true, LoadSceneMode mode = LoadSceneMode.Single)
{
MonoManager.Instance.StartCoroutine(LoadSceneCoroutine(sceneName, loading, completed, setActiveAfterCompleted, mode));
}
private IEnumerator LoadSceneCoroutine(string sceneName, UnityAction<float> loading = null, UnityAction<AsyncOperation> completed = null, bool setActiveAfterCompleted = true, LoadSceneMode mode = LoadSceneMode.Single)
{
// 开始加载资源
AsyncOperation asyncOperation = SceneManager.LoadSceneAsync(sceneName, mode);
asyncOperation.allowSceneActivation = false;
// 等待资源加载完毕
while (asyncOperation.progress < 0.9f)
{
loading?.Invoke(asyncOperation.progress);
yield return null;
}
// 人为将进度设置为1,以便外部进度条的显示
loading?.Invoke(1);
// 根据设置决定何时激活场景
asyncOperation.allowSceneActivation = setActiveAfterCompleted;
// 加载资源完毕后执行的逻辑
completed?.Invoke(asyncOperation);
}
测试调用
public class SceneTest : MonoBehaviour
{
private void Start()
{
LoadSceneManager.Instance.LoadSceneAsync(1, Loading, Completed);
}
void Loading(float progress)
{
Debug.Log($"加载进度是{progress*100}%");
}
void Completed(AsyncOperation asyncOperation)
{
Debug.Log("场景加载完成");
}
}
结果
4、完整代码
using System;
using System.Collections;
using System.Collections.Generic;
using PlasticGui.WorkspaceWindow;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.SceneManagement;
namespace XYFrame
{
/// <summary>
/// 切换场景的管理器。用于加载场景和切换场景。
/// </summary>
public class LoadSceneManager : Singleton<LoadSceneManager>
{
#region 同步加载场景
/// <summary>
/// <para>同步加载场景(通过索引)</para>
/// </summary>
/// <param name="sceneBuildIndex">场景的索引</param>
/// <param name="mode">加载场景的模式。默认是LoadSceneMode.Single,表示会卸载原来的场景,再切换到新场景。LoadSceneMode.Additive表示会将新场景叠加在原来的场景中。</param>
public void LoadScene(int sceneBuildIndex, LoadSceneMode mode = LoadSceneMode.Single)
{
SceneManager.LoadScene(sceneBuildIndex, mode);
}
/// <summary>
/// <para>同步加载场景(通过名字)</para>
/// </summary>
/// <param name="sceneName">场景的名字</param>
/// <param name="mode">加载场景的模式。默认是LoadSceneMode.Single,表示会卸载原来的场景,再切换到新场景。LoadSceneMode.Additive表示会将新场景叠加在原来的场景中。</param>
public void LoadScene(string sceneName, LoadSceneMode mode)
{
SceneManager.LoadScene(sceneName, mode);
}
/// <summary>
/// <para>同步重新加载当前的活动场景</para>
/// </summary>
public void LoadActiveScene()
{
SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);
}
/// <summary>
/// <para>同步加载下一个场景</para>
/// </summary>
/// <param name="isCyclical">是否循环加载场景。</param>
public void LoadNextScene(bool isCyclical = false)
{
int buildIndex = SceneManager.GetActiveScene().buildIndex + 1;
if (buildIndex > SceneManager.sceneCountInBuildSettings - 1)
{
if (isCyclical)
{
buildIndex = 0;
}
else
{
Debug.LogWarning($"加载场景失败!要加载的场景的索引是{buildIndex},超过了当前Build Settings窗口中的最大索引。");
return;
}
}
SceneManager.LoadScene(buildIndex);
}
/// <summary>
/// <para>同步加载上一个场景</para>
/// </summary>
/// <param name="isCyclical">是否循环加载场景。</param>
public void LoadPreviousScene(bool isCyclical = false)
{
int buildIndex = SceneManager.GetActiveScene().buildIndex - 1;
if (buildIndex < 0)
{
if (isCyclical)
{
buildIndex = SceneManager.sceneCountInBuildSettings - 1;
}
else
{
Debug.LogWarning($"加载场景失败!要加载的场景的索引是{buildIndex},没有索引为负数的场景。");
return;
}
}
SceneManager.LoadScene(buildIndex);
}
#endregion
#region 异步加载场景
/// <summary>
/// <para>异步加载场景(通过索引)</para>
/// </summary>
/// <param name="sceneBuildIndex">要加载的场景索引。</param>
/// <param name="loading">加载中的回调。只要在加载中,就会不断地执行这个回调。一般用于进度条的显示。</param>
/// <param name="completed">加载完毕后的回调。</param>
/// <param name="setActiveAfterCompleted">加载场景完毕后,是否切换到该场景。</param>
/// <param name="mode">加载场景的模式。默认是LoadSceneMode.Single,表示会卸载原来的场景,再切换到新场景。LoadSceneMode.Additive表示会将新场景叠加在原来的场景中。</param>
public void LoadSceneAsync(int sceneBuildIndex, UnityAction<float> loading = null, UnityAction<AsyncOperation> completed = null, bool setActiveAfterCompleted = true, LoadSceneMode mode = LoadSceneMode.Single)
{
//如果要加载的场景的索引不合法,则返回。
if (!IsSceneBuildIndexValid(sceneBuildIndex)) return;
//开启协程进行异步加载。
MonoManager.Instance.StartCoroutine(LoadSceneAsyncCoroutine(sceneBuildIndex, loading, completed, setActiveAfterCompleted, mode));
}
IEnumerator LoadSceneAsyncCoroutine(int sceneBuildIndex, UnityAction<float> loading = null, UnityAction<AsyncOperation> completed = null, bool setActiveAfterCompleted = true, LoadSceneMode mode = LoadSceneMode.Single)
{
//异步操作对象,记录了异步操作的数据。
AsyncOperation asyncOperation = SceneManager.LoadSceneAsync(sceneBuildIndex, mode);
//设置为false,则即使场景加载完毕,也不会切换过去。当场景加载完毕,再次把这个值复制为true,才会切换过去。
asyncOperation.allowSceneActivation = false;
//加载场景的过程中,提供给外部执行的回调。一般用于进度条的显示。
while (asyncOperation.progress < 0.9f)
{
loading?.Invoke(asyncOperation.progress);
yield return CoroutineTool.WaitForFrame();
}
//当asyncOperation.allowSceneActivation为false,则asyncOperation.progress最多只能到达0.9,我们人为让它凑成整数1,方便外部进度条的显示。
loading?.Invoke(1f);
//加载场景完毕之后,如果把这个变量设置为true,则会切换到该场景。如果为false,则不会切换到该场景。
asyncOperation.allowSceneActivation = setActiveAfterCompleted;
//加载场景完毕之后执行的回调。
completed?.Invoke(asyncOperation);
}
/// <summary>
/// <para>异步加载场景(通过名称)</para>
/// </summary>
/// <param name="sceneName">要加载的场景名</param>
/// <param name="loading">加载中的回调。只要在加载中,就会不断地执行这个回调。一般用于进度条的显示。</param>
/// <param name="completed">加载完毕后的回调。</param>
/// <param name="setActiveAfterCompleted">加载场景完毕后,是否切换到该场景。</param>
/// <param name="mode">加载场景的模式。默认是LoadSceneMode.Single,表示会卸载原来的场景,再切换到新场景。LoadSceneMode.Additive表示会将新场景叠加在原来的场景中。</param>
public void LoadSceneAsync(string sceneName, UnityAction<float> loading = null, UnityAction<AsyncOperation> completed = null, bool setActiveAfterCompleted = true, LoadSceneMode mode = LoadSceneMode.Single)
{
//开启协程进行异步加载。
MonoManager.Instance.StartCoroutine(LoadSceneAsyncCoroutine(sceneName, loading, completed, setActiveAfterCompleted, mode));
}
IEnumerator LoadSceneAsyncCoroutine(string sceneName, UnityAction<float> loading = null, UnityAction<AsyncOperation> completed = null, bool setActiveAfterCompleted = true, LoadSceneMode mode = LoadSceneMode.Single)
{
//异步操作对象,记录了异步操作的数据。
AsyncOperation asyncOperation = SceneManager.LoadSceneAsync(sceneName, mode);
//设置为false,则即使场景加载完毕,也不会切换过去。当场景加载完毕,再次把这个值复制为true,才会切换过去。
asyncOperation.allowSceneActivation = false;
//加载场景的过程中,提供给外部执行的回调。一般用于进度条的显示。
while (asyncOperation.progress < 0.9f)
{
loading?.Invoke(asyncOperation.progress);
yield return CoroutineTool.WaitForFrame();
}
//当asyncOperation.allowSceneActivation为false,则asyncOperation.progress最多只能到达0.9,我们人为让它凑成整数1,方便外部进度条的显示。
loading?.Invoke(1f);
//加载场景完毕之后,如果把这个变量设置为true,则会切换到该场景。如果为false,则不会切换到该场景。
asyncOperation.allowSceneActivation = setActiveAfterCompleted;
//加载场景完毕之后执行的回调。
completed?.Invoke(asyncOperation);
}
/// <summary>
/// <para>异步加载当前活动场景。</para>
/// </summary>
/// <param name="loading">加载中的回调。只要在加载中,就会不断地执行这个回调。一般用于进度条的显示。</param>
/// <param name="completed">加载完毕后的回调。</param>
/// <param name="setActiveAfterCompleted">加载场景完毕后,是否切换到该场景。</param>
/// <param name="mode">加载场景的模式。默认是LoadSceneMode.Single,表示会卸载原来的场景,再切换到新场景。LoadSceneMode.Additive表示会将新场景叠加在原来的场景中。</param>
public void LoadActiveSceneAsync(UnityAction<float> loading = null, UnityAction<AsyncOperation> completed = null, bool setActiveAfterCompleted = true, LoadSceneMode mode = LoadSceneMode.Single)
{
LoadSceneAsync(SceneManager.GetActiveScene().buildIndex, loading, completed, setActiveAfterCompleted, mode);
}
/// <summary>
/// 异步加载下一个场景。
/// </summary>
/// <param name="isCyclical">是否循环加载场景。</param>
/// <param name="loading">加载中的回调。只要在加载中,就会不断地执行这个回调。一般用于进度条的显示。</param>
/// <param name="completed">加载完毕后的回调。</param>
/// <param name="setActiveAfterCompleted">加载场景完毕后,是否切换到该场景。</param>
/// <param name="mode">加载场景的模式。默认是LoadSceneMode.Single,表示会卸载原来的场景,再切换到新场景。LoadSceneMode.Additive表示会将新场景叠加在原来的场景中。</param>
public void LoadNextSceneAsync(bool isCyclical = false, UnityAction<float> loading = null, UnityAction<AsyncOperation> completed = null, bool setActiveAfterCompleted = true, LoadSceneMode mode = LoadSceneMode.Single)
{
//下一个场景的索引。
int buildIndex = SceneManager.GetActiveScene().buildIndex + 1;
//当要加载的场景的索引超过了Build Settings窗口中的最大索引,则根据参数来判断是否循环加载场景。
if (buildIndex > SceneManager.sceneCountInBuildSettings - 1)
{
if (isCyclical)
{
buildIndex = 0;
}
else
{
Debug.LogWarning($"加载场景失败!要加载的场景的索引是{buildIndex},超过了当前Build Settings窗口中的最大索引。");
return;
}
}
//异步加载该场景。
LoadSceneAsync(buildIndex, loading, completed, setActiveAfterCompleted, mode);
}
/// <summary>
/// 异步加载上一个场景。
/// </summary>
/// <param name="isCyclical">是否循环加载场景。</param>
/// <param name="loading">加载中的回调。只要在加载中,就会不断地执行这个回调。一般用于进度条的显示。</param>
/// <param name="completed">加载完毕后的回调。</param>
/// <param name="setActiveAfterCompleted">加载场景完毕后,是否切换到该场景。</param>
/// <param name="mode">加载场景的模式。默认是LoadSceneMode.Single,表示会卸载原来的场景,再切换到新场景。LoadSceneMode.Additive表示会将新场景叠加在原来的场景中。</param>
public void LoadPreviousSceneAsync(bool isCyclical = false, UnityAction<float> loading = null, UnityAction<AsyncOperation> completed = null, bool setActiveAfterCompleted = true, LoadSceneMode mode = LoadSceneMode.Single)
{
//上一个场景的索引。
int buildIndex = SceneManager.GetActiveScene().buildIndex - 1;
//当要加载的场景的索引为负数,则根据参数来判断是否循环加载场景。
if (buildIndex < 0)
{
if (isCyclical)
{
buildIndex = SceneManager.sceneCountInBuildSettings - 1;
}
else
{
Debug.LogWarning($"加载场景失败!要加载的场景的索引是{buildIndex},没有索引为负数的场景。");
return;
}
}
//异步加载该场景。
LoadSceneAsync(buildIndex, loading, completed, setActiveAfterCompleted, mode);
}
#endregion
#region 异步销毁场景和这个场景中的所有游戏对象
/// <summary>
/// <para>按索引销毁指定的场景和这个场景中的所有游戏对象。</para>
/// <para>本方法只对加载时用了LoadSceneMode.Additive来加载的场景有效。如果当前游戏中只有一个场景,则本方法无效,且会在控制台报黄色的警告。</para>
/// <para>本方法不会释放内存中的场景资源,如果要释放该场景资源,应在调用这个方法后,再调用Resources.UnloadUnusedAssets方法。</para>
/// </summary>
/// <param name="sceneBuildIndex">要销毁的场景索引。</param>
/// <param name="callback">销毁完毕后执行的回调。</param>
/// <param name="options">销毁场景的选项。是一个UnloadSceneOptions型枚举。</param>
public void DestroySceneAsync(int sceneBuildIndex, UnityAction callback = null, UnloadSceneOptions options = UnloadSceneOptions.None)
{
MonoManager.Instance.StartCoroutine(DestroySceneCoroutine(sceneBuildIndex, callback, options));
}
IEnumerator DestroySceneCoroutine(int sceneBuildIndex, UnityAction callback = null, UnloadSceneOptions options = UnloadSceneOptions.None)
{
//异步操作对象,记录了异步操作的数据。
AsyncOperation asyncOperation = SceneManager.UnloadSceneAsync(sceneBuildIndex, options);
if (asyncOperation == null)
{
Debug.LogWarning("要销毁的场景不合法,销毁无效!");
yield break;
}
//如果没有卸载完成,则停在这里面等待。
while (asyncOperation.progress < 0.9f)
yield return CoroutineTool.WaitForFrame();
//卸载场景完毕之后执行的回调。
callback?.Invoke();
}
/// <summary>
/// <para>按名称销毁指定的场景和这个场景中的所有游戏对象。</para>
/// <para>本方法只对加载时用了LoadSceneMode.Additive来加载的场景有效。如果当前游戏中只有一个场景,则本方法无效,且会在控制台报黄色的警告。</para>
/// <para>本方法不会释放内存中的场景资源,如果要释放该场景资源,应在调用这个方法后,再调用Resources.UnloadUnusedAssets方法。</para>
/// </summary>
/// <param name="sceneName">要销毁的场景名或场景路径。</param>
/// <param name="callback">销毁完毕后执行的回调。</param>
/// <param name="options">销毁场景的选项。是一个UnloadSceneOptions型枚举。</param>
public void DestroySceneAsync(string sceneName, UnityAction callback = null, UnloadSceneOptions options = UnloadSceneOptions.None)
{
MonoManager.Instance.StartCoroutine(DestroySceneCoroutine(sceneName, callback, options));
}
IEnumerator DestroySceneCoroutine(string sceneName, UnityAction callback = null, UnloadSceneOptions options = UnloadSceneOptions.None)
{
//异步操作对象,记录了异步操作的数据。
AsyncOperation asyncOperation = SceneManager.UnloadSceneAsync(sceneName, options);
if (asyncOperation == null)
{
Debug.LogWarning("要销毁的场景不合法,销毁无效!");
yield break;
}
//如果没有卸载完成,则停在这里面等待。
while (asyncOperation.progress < 0.9f)
yield return CoroutineTool.WaitForFrame();
//卸载场景完毕之后执行的回调。
callback?.Invoke();
}
/// <summary>
/// <para>按场景对象销毁指定的场景和这个场景中的所有游戏对象。</para>
/// <para>本方法只对加载时用了LoadSceneMode.Additive来加载的场景有效。如果当前游戏中只有一个场景,则本方法无效,且会在控制台报黄色的警告。</para>
/// <para>本方法不会释放内存中的场景资源,如果要释放该场景资源,应在调用这个方法后,再调用Resources.UnloadUnusedAssets方法。</para>
/// </summary>
/// <param name="scene">要销毁的场景对象。</param>
/// <param name="callback">销毁完毕后执行的回调。</param>
/// <param name="options">销毁场景的选项。是一个UnloadSceneOptions型枚举。</param>
public void DestroySceneAsync(Scene scene, UnityAction callback = null, UnloadSceneOptions options = UnloadSceneOptions.None)
{
MonoManager.Instance.StartCoroutine(DestroySceneCoroutine(scene, callback, options));
}
IEnumerator DestroySceneCoroutine(Scene scene, UnityAction callback = null, UnloadSceneOptions options = UnloadSceneOptions.None)
{
//异步操作对象,记录了异步操作的数据。
AsyncOperation asyncOperation = SceneManager.UnloadSceneAsync(scene, options);
if (asyncOperation == null)
{
Debug.LogWarning("要销毁的场景不合法,销毁无效!");
yield break;
}
//如果没有卸载完成,则停在这里面等待。
while (asyncOperation.progress < 0.9f)
yield return CoroutineTool.WaitForFrame();
//卸载场景完毕之后执行的回调。
callback?.Invoke();
}
#endregion
#region 返回场景所有游戏对象
/// <summary>
/// <para>获取当前激活场景里的所有游戏对象</para>
/// <para>隐藏的根游戏对象也会包含在其中。DontDestroyOnLoad的游戏对象不包含在其中。</para>
/// </summary>
public GameObject[] GetActiveSceneRootGameObjects()
{
return SceneManager.GetActiveScene().GetRootGameObjects();
}
/// <summary>
/// <para>获取所有加载的场景里的所有游戏对象</para>
/// <para>隐藏的根游戏对象也会包含在其中。DontDestroyOnLoad的游戏对象不包含在其中。</para>
/// </summary>
public GameObject[] GetLoadedScenesRootGameObjects()
{
List<GameObject> list = new List<GameObject>();
//把当前所有加载的场景的根游戏对象都逐一存储到列表中。
for (int i = 0; i < SceneManager.sceneCount; i++)
list.AddRange(SceneManager.GetSceneAt(i).GetRootGameObjects());
return list.ToArray();
}
#endregion
/// <summary>
/// 判断指定的场景索引是否合法。
/// </summary>
/// <param name="buildIndex">指定的场景索引</param>
bool IsSceneBuildIndexValid(int buildIndex)
{
if (buildIndex < 0)
{
Debug.LogWarning($"要加载的场景的索引不合法!该索引是{buildIndex},不能为负数。");
return false;
}
if (buildIndex > SceneManager.sceneCountInBuildSettings - 1)
{
Debug.LogWarning($"要加载的场景的索引不合法!该索引越界,越界的索引是{buildIndex},但是场景最大的索引是{SceneManager.sceneCountInBuildSettings - 1}。");
return false;
}
return true;
}
}
}
完结
赠人玫瑰,手有余香!如果文章内容对你有所帮助,请不要吝啬你的点赞评论和关注
,你的每一次支持
都是我不断创作的最大动力。当然如果你发现了文章中存在错误
或者有更好的解决方法
,也欢迎评论私信告诉我哦!
好了,我是向宇
,https://xiangyu.blog.csdn.net
一位在小公司默默奋斗的开发者,闲暇之余,边学习边记录分享,站在巨人的肩膀上,通过学习前辈们的经验总是会给我很多帮助和启发!如果你遇到任何问题,也欢迎你评论私信或者加群找我, 虽然有些问题我也不一定会,但是我会查阅各方资料,争取给出最好的建议,希望可以帮助更多想学编程的人,共勉~