切换场景:LoadScene、加载界面,以及什么会存活下来
怎么在 Unity 里切换到另一个场景?
把每个场景都加进 File > Build Profiles 里的 Scene List,然后用场景名调用 SceneManager.LoadScene。切换发生在下一帧,旧场景里的一切都会被销毁,只有标记了 DontDestroyOnLoad 的根物体能存活——以及静态字段和 Time.timeScale,这些没有任何人会替你重置。
加载另一个 scene 只要一行。所有麻烦都出在这行周围:scene 从来没被加进构建、后面的代码还在接着跑、或者你正需要的东西已经跟着旧 scene 一起被丢掉了。
第 1 步 — 把 scene 放进列表
- 1
打开 (Unity 6 之前叫 ),找到 Scene List。
- 2
把你想放进游戏里的每个 scene 都打开,然后按 Add Open Scenes,或者直接把 .unity 文件从 Project 面板拖进来。
- 3
位于 index 0 的那个,就是构建出来的游戏启动时进入的 scene。把菜单、或者开场放到最上面。
第 2 步 — 加载它
using UnityEngine;
using UnityEngine.SceneManagement; // without this line, SceneManager is not found
public class Doorway : MonoBehaviour
{
public void Play()
{
SceneManager.LoadScene("Arena"); // by name, as spelt in the Scene List
}
public void Restart()
{
// The scene that is running, whatever it is called.
SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);
}
}什么能挺过加载,什么不能
旧 scene 里的每个 GameObject 都会被销毁。指向它们的引用变成 null,跑在它们上面的 coroutine 也就停在原地。
标了
DontDestroyOnLoad的 object 会继续活着 —— 但只有当它是没有父物体的根 object 时才成立。最常留下的是背景音乐、存在内存里的存档,还有 一个 manager。static 字段不属于任何 scene,所以它的值会保留下来。把关卡编号带过去很方便;但如果上一次运行剩下的值还躺在那里,它就是个坑。
Time.timeScale 是全局的。用 timeScale = 0 暂停了游戏,然后加载菜单却忘了把它调回 1,菜单就会卡死着打开 —— 而且没有任何报错来解释原因。
加载画面:给那些要等一下的 scene
using System.Collections;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
public class Loader : MonoBehaviour
{
public Slider bar;
public void Load(string scene) => StartCoroutine(LoadRoutine(scene));
IEnumerator LoadRoutine(string scene)
{
AsyncOperation op = SceneManager.LoadSceneAsync(scene);
while (!op.isDone)
{
// progress stops at 0.9 while the scene waits its turn to appear,
// so scale it back up or the bar never reaches the end.
bar.value = Mathf.Clamp01(op.progress / 0.9f);
yield return null;
}
}
}同时存在两个 scene
LoadSceneMode.Additive 不是替换掉正在运行的 scene,而是把一个 scene 叠在它上面:比如永远不用再加载的 HUD,或者在主场景旁边流式加载进来的关卡。要撤掉就用 UnloadSceneAsync,并且记住:新生成的 object 会落在当前是 active 的那个 scene 里。
做出这个的那一课
界面、面板与 GameManager
这篇指南单独成篇,是一份可以直接照着做的配方。在课程里,同样的东西会作为贯穿全部五个章的那个项目的一部分来搭建 —— 基础,第 10 课。