准备工作
之前对于场景切换没有明确的做个测试,只是避开场景与场景之间的资源关联。现在需要去做资源管理,顺便就来测试下。
每个场景里面都放一个GameObject用来打印Log,我们通过Log的顺序来知道执行的顺序,然后再通过查看Profiler来查看当前内存加载的资源情况。
脚本
ChangeScene .cs 用来控制切换场景
public class ChangeScene : MonoBehaviour {
public string sceneName;
AsyncOperation asyncOperation;
void OnGUI()
{
sceneName = GUILayout.TextField(sceneName);
if (GUILayout.Button("Change"))
{
asyncOperation = Application.LoadLevelAsync(sceneName);
asyncOperation.allowSceneActivation = false;
Debug.Log("allowSceneActivation : " + asyncOperation.allowSceneActivation);
}
if (GUILayout.Button("SceneActivatio") && asyncOperation != null)
{
asyncOperation.allowSceneActivation = true;
Debug.Log("allowSceneActivation : " + asyncOperation.allowSceneActivation);
}
}
}
CTest.cs
using UnityEngine;
using System.Collections;
public class CTest : MonoBehaviour {
void Awake()
{
Debug.Log("Awake : " + gameObject.name);
}
void Start()
{
Debug.Log("Start : " + gameObject.name);
}
void OnEnable()
{
Debug.Log("OnEnable : " + gameObject.name);
}
void OnLevelWasLoaded()
{
Debug.Log("OnLevelWasLoaded : " + gameObject.name);
}
void OnDestroy()
{
Debug.Log("OnDestroy : " + gameObject.name);
}
}
场景对象
我们创建3个场景 A B C
A:只放两个GameObject分别挂上脚本ChangeScene和CTest
B: 放入一个Cube并引用一张贴图,再放入一个GameObject挂上脚本CTest
C:一个空场景什么都不放
开始测试
先运行A场景,打印情况如下。 同时也能知道,当前并没有加载我们测试的那张贴图”long”
然后我们输入B,点击Change。也就是调用
asyncOperation = Application.LoadLevelAsync("B");
asyncOperation.allowSceneActivation = false;
当allowSceneActivation为false时,只会将场景加载进去,当他的值为true的时候,才会执行切换操作
看图发现已经将贴图加载进内存了,但是场景里面并没有发生任何变化。
我们将allowSceneActivation设置为true,场景就切换到B了。这是日志打印情况
至此,我们就知道场景切换的顺序流程了
但是还有一点,需要确认场景切换,资源释放的问题,于是我们继续将场景切换到C,也就是没有任何资源的Scene。
当我切换到C以后,去查看Profiler,发现资源已经释放了。
想到Unity管理资源如果有引用则不释放的思路,去做了一个测试。我写了一个脚本,把B里面的材质保存起来,再从B切换到C。当然这个脚本对象也做了DontDestroyOnLoad,不会被销毁。
运行测试,果然是这样,可以看到资源并没有被释放。
结论
首先执行LoadLevelAsync的时候,先加载引用的全部资源
- 当allowSceneActivation为true后,开始执行切换场景
- 删除当前场景的所有对象,触发当前场景的OnDestroy
- 创建新场景里的所有对象,触发Awake OnEnable
- 触发OnLevelWasLoaded
- 剩下的就是正常流程触发场景对象的Start然后就是Update了
场景引用的的资源会在切换的时候尝试从内存卸载销毁,如果没有被其他地方引用,则会直接从内存卸载销毁,反之则不会被销毁。