Unity基础 —— 多场景管理与 DontDestroyOnLoad

多场景管理与 DontDestroyOnLoad

在 Unity 中,默认的场景加载方式会销毁当前场景的所有对象并加载新场景。为了实现持久化的全局功能或无缝的大世界体验,需要使用多场景管理技术。


1. DontDestroyOnLoad (DDOL)

DontDestroyOnLoad 是一个方法,用于将指定的 GameObject 从当前场景移到一个特殊的 "DontDestroyOnLoad" 根节点下,使其在场景切换时不会被卸载。

  • 适用对象: 全局唯一的管理器,如 AudioManager(背景音乐连续播放)、NetworkManager(保持网络连接)、DataManager(存储玩家临时状态)。
  • 代码示例:
    using UnityEngine;
    
    public class GlobalManager : MonoBehaviour
    {
        public static GlobalManager Instance;
    
        void Awake()
        {
            // 单例模式配合 DDOL
            if (Instance == null)
            {
                Instance = this;
                DontDestroyOnLoad(gameObject);
            }
            else
            {
                // 关键点:防止重复从新场景加载导致出现多个实例
                Destroy(gameObject);
            }
        }
    }
    

2. Additive 模式(叠加加载)

除了传统的 Single 模式(关闭旧的加载新的),Unity 支持使用 LoadSceneMode.Additive 模式。

  • 原理: 在不销毁当前场景的前提下,将另一个场景的内容“叠加”到当前层级中。

  • 应用场景:

    • 大世界分块加载: 当玩家移动到某个区域时,异步加载相邻区域的场景。
    • 固定背景: 一个场景专门放 UI 和核心管理器,另一个场景放具体的关卡内容。
  • 代码示例:

    using UnityEngine;
    using UnityEngine.SceneManagement;
    
    public class SceneLoader : MonoBehaviour
    {
        public void LoadLevelAdditive(string sceneName)
        {
            // 异步叠加加载
            SceneManager.LoadSceneAsync(sceneName, LoadSceneMode.Additive);
        }
    
        public void UnloadLevel(string sceneName)
        {
            // 卸载不再需要的场景
            SceneManager.UnloadSceneAsync(sceneName);
        }
    }
    

3. 主动场景 (Active Scene)

当多个场景同时存在时,Unity 会有一个 Active Scene

  • 影响: 新生成的物体会默认出现在 Active Scene 中;环境光照(Lighting Settings)和重力等物理设置也以 Active Scene 为准。
  • 代码设置: SceneManager.SetActiveScene(Scene scene);

4. 面试核心考点

  • Q: DDOL 会导致内存泄漏吗?
    • A: 会。如果 DDOL 的物体内部引用了大量已销毁场景中的资源(如贴图、材质),由于 DDOL 根节点一直存在,这些资源将无法被 GC 回收。
  • Q: 如何处理 DDOL 物体的单例重复问题?
    • A: 必须在 Awake 中检查静态实例 Instance。如果已存在,则 Destroy(gameObject)。否则,每次回到初始场景都会多出一个管理器。
  • Q: 场景加载时的 Loading 进度条怎么实现?
    • A: 使用 AsyncOperation。通过 AsyncOperation.progress 获取 0 到 1 的加载数值,但要注意 Unity 在 0.9 时会停住(等待激活),需处理 allowSceneActivation 属性。
  • Q: 叠加加载时,两个场景有同名的 GameObject 会冲突吗?
    • A: 不会冲突,它们在内存中是独立的对象。但如果脚本逻辑通过 GameObject.Find 查找,可能会找错对象。建议使用特定的 Tag 或直接引用。
posted @ 2026-04-16 12:23  Reed_Chill  阅读(106)  评论(0)    收藏  举报