个人主页 阿松爱睡觉横竖醒不来你可以不屠龙但不能不磨剑目录一、前言二、监听方法一SceneManager.sceneLoaded事件二SceneManager.LoadSceneAsync回调三协程方式三、结语一、前言在游戏开发的过程中各个Scene场景之间的切换加载是必要的。但有些时候我们也需要知道场景什么时候切换加载完毕以便于在场景加载完毕的时候执行特定的函数。所以下面就聊一聊场景切换完成时机的获取方法就是监听一下场景什么时候加载完毕。二、监听方法一SceneManager.sceneLoaded事件第一个也是比较简单便捷的方法通过订阅SceneManager.sceneLoaded事件来监听场景加载完成的情况。用法比较简单看下示例usingUnityEngine;usingUnityEngine.SceneManagement;publicclassSceneLoadListener:MonoBehaviour{privatevoidOnEnable(){// 订阅场景加载完成的事件SceneManager.sceneLoadedOnSceneLoaded;}privatevoidOnDisable(){// 取消订阅场景加载完成的事件SceneManager.sceneLoaded-OnSceneLoaded;}//scene 加载的场景、mode 加载场景的模式privatevoidOnSceneLoaded(Scenescene,LoadSceneModemode){// 处理场景加载完成后的逻辑Debug.Log(场景加载完毕scene.name);}}脚本编写完毕之后将该监听的脚本挂载到任何活跃的GameObject上即可它会监听场景加载事件。当场景加载完成时OnSceneLoaded方法自动被调用。这里有一点需要注意就是脚本挂载的地方需要保持挂载了该脚本的物体持续活跃为什么这么讲假设挂载了该脚本的物体在某个场景中而且这个场景还刚好是被切换下的旧的场景一旦含有该物体的场景被切换那么场景里面的物体也同样被销毁那么该脚本就会在场景加载完成前取消订阅那么也就不会监听到场景加载完毕事件。对于这种情况有两种方法可以避免。第一个就是使用DontDestroyOnLoad()固定持久化这个方法不明白的可以看我的另一篇文章有专门的讲解第二个就是把加载场景的方式换成LoadSceneMode.Additive这样就不会关闭之前正在加载的场景。二SceneManager.LoadSceneAsync回调第二个是使用SceneManager.LoadSceneAsync来异步加载场景然后可以通过其返回的AsyncOperation对象来监听加载完成。还是先看下示例usingUnityEngine;usingUnityEngine.SceneManagement;publicclassSceneLoadAsync:MonoBehaviour{//加载场景的方法publicvoidLoadSceneAsync(stringsceneName){SceneManager.LoadSceneAsync(sceneName,LoadSceneMode.Single).completedoperation{// 在这里处理场景加载完成后的逻辑Debug.Log(场景加载完毕sceneName);};//上面是比较简洁的写法没用使用AsyncOperation类型的变量来存储返回的AsyncOperation对象AsyncOperationasyncOperationSceneManager.LoadSceneAsync(sceneName,LoadSceneMode.Single);asyncOperation.completedoperation{// 在这里处理场景加载完成后的逻辑Debug.Log(场景加载完毕sceneName);};}}看完可能会注意到回调函数中带有一个名为operation的参数这个参数代表当前完成的异步操作所以它的类型是AsyncOperation类型。那么可以从这个参数获取到什么数据呢这个参数类型(AsyncOperation)中有四个变量allowSceneActivation允许在场景准备就绪后立即激活场景。(bool类型)isDone操作是否已完成只读(bool类型)priority允许调整执行异步操作调用的顺序。(int类型)progress获取操作进度。只读(float类型)比较常用的就只有isDone和progress下面第三中方法中就用到了isDone变量一起来看下。三协程方式这种方法其实跟上面的二是类似的都是使用的SceneManager.LoadSceneAsync返回的AsyncOperation对象只不过不同的是这里没有用AsyncOperation对象中的completed事件而是检测的对象中的isDone变量。看下示例usingUnityEngine;usingUnityEngine.SceneManagement;usingSystem.Collections;publicclassSceneLoadCoroutine:MonoBehaviour{//加载场景函数publicvoidLoadScene(stringsceneName){//启动协程StartCoroutine(LoadSceneAsync(sceneName));}//协程加载IEnumeratorLoadSceneAsync(stringsceneName){AsyncOperationasyncLoadSceneManager.LoadSceneAsync(sceneName);// 等待场景加载完成while(!asyncLoad.isDone){yieldreturnnull;}// 在这里处理场景加载完成后的逻辑Debug.Log(场景加载完毕sceneName);}}LoadScene方法启动了一个协程该协程等待AsyncOperation的isDone为true指示场景加载完成。这种方法有个好处就是可以获取场景加载的进度就是前面说的progress变量可以用来做个进度条什么的。三、结语这篇的内容就到此结束了如果遇到什么问题欢迎在评论区留言或者私信下期见拜拜