Scene
Scene 是容纳所有 GameObject、灯光与摄像机的空间——每个 .unity 文件就是一个 Scene:关卡、菜单或独立游戏状态。用 SceneManager 切换场景,LoadSceneAsync 可配加载界面;DontDestroyOnLoad 让跨关卡对象存活。它是 Unity 项目管理与流程设计骨架。
想象一下...
Scene 就像一集电视剧。每一集有自己的布景、角色和剧情。切到下一集(加载 Scene)时,旧布景消失。需要跨集存活的角色用 DontDestroyOnLoad()——像主角,关卡切换也从不消失。
概念详解
典型游戏有许多 Scene: MainMenu、Level_01、Level_02、GameOver、Loading… 拆分 它们有助于控制内存——只加载当前需要的内容。
切换 Scene 使用 SceneManager 类。LoadScene() 是同步的
(会阻塞——游戏卡住),而 LoadSceneAsync() 在后台加载,方便
显示 Loading Screen。
Additive Loading:同时加载多个 Scene,彼此叠加。 常用于世界流式加载,或把 UI Scene 与玩法 Scene 拆开。
需要跨 Scene 存活的 GameObject 使用 DontDestroyOnLoad(gameObject)。务必
配合 Singleton,避免 Scene 重载时再生成一份副本。
Scene 流程
MainMenu
index: 0
Loading
index: 1
Level_01
index: 2
GameOver
index: 3
Single Mode
加载新 Scene → 卸载旧 Scene
Additive Mode
额外加载 → 保留旧 Scene
动手步骤
创建新 Scene
菜单 File → New Scene 创建 Scene。
加入 Build Settings
File → Build Settings → 把 .unity 文件拖进列表。索引号就是 LoadScene(index) 用的数字。
用脚本切换 Scene
加上 using UnityEngine.SceneManagement;,再调用 SceneManager.LoadScene()。
用 Async 做 Loading Screen
用 Coroutine + LoadSceneAsync(),读取 AsyncOperation.progress(0.0 → 0.9)更新进度条。
交互模拟器
点击 Load Scene 模拟带 Loading Screen 的切换。观察 GameManager 如何跨 Scene 存活。
🔒 GameManager
DontDestroyOnLoad
代码示例
基础using UnityEngine;
using UnityEngine.SceneManagement;
public class SceneBasics : MonoBehaviour
{
void Awake()
{
// Keep this object across every Scene (Singleton GameManager)
DontDestroyOnLoad(gameObject);
}
public void LoadLevel1()
=> SceneManager.LoadScene("Level_01"); // by name
public void RestartCurrentScene()
{
int idx = SceneManager.GetActiveScene().buildIndex;
SceneManager.LoadScene(idx); // by index
}
public void LoadNextScene()
{
int next = SceneManager.GetActiveScene().buildIndex + 1;
SceneManager.LoadScene(next);
}
}代码示例
进阶using System.Collections;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
public class SceneLoader : MonoBehaviour
{
public static SceneLoader Instance { get; private set; }
[SerializeField] private Slider progressBar;
void Awake()
{
// Singleton: only one instance may exist
if (Instance != null) { Destroy(gameObject); return; }
Instance = this;
DontDestroyOnLoad(gameObject);
}
public void LoadScene(string sceneName)
=> StartCoroutine(LoadAsync(sceneName));
private IEnumerator LoadAsync(string sceneName)
{
AsyncOperation op = SceneManager.LoadSceneAsync(sceneName);
op.allowSceneActivation = false;
while (op.progress < 0.9f)
{
float progress = Mathf.Clamp01(op.progress / 0.9f);
if (progressBar) progressBar.value = progress;
yield return null;
}
if (progressBar) progressBar.value = 1f;
yield return new WaitForSeconds(0.5f);
op.allowSceneActivation = true;
}
}📌 快速记忆
- ▸Scene 必须先加入 Build Settings,LoadScene 才能找到
- ▸
DontDestroyOnLoad让对象跨切换存活 - ▸用 Async + Coroutine 做 Loading Screen
- ▸
Additive模式用于世界流式加载和拆分 UI
⚠️ 常见错误
❌ 忘记把 Scene 加入 Build Settings
报错 "Scene not found in Build Settings"
✅ File → Build Settings → Add Open Scenes
❌ DontDestroyOnLoad 却没有 Singleton 守卫
重载 Scene 会生成第二个 GameManager
✅ if (Instance != null) Destroy(this);