如何解决使用DontDestroyOnLoad后重载场景时GameObject重复问题?
解决Unity关卡切换时重复生成保留对象的问题
核心问题是:用DontDestroyOnLoad保留的对象不会随场景销毁,但重新加载场景时,场景内的原始对象会被再次实例化,导致多个相同对象共存。用单例模式就能简单解决这个问题,确保每个需要保留的对象只有一个实例存在。
具体实现步骤
1. 创建通用持久化脚本
给需要跨场景保留的对象(比如玩家)挂一个脚本,命名为PersistentObject.cs,代码如下:
using UnityEngine; public class PersistentObject : MonoBehaviour { // 静态变量,存储该类型对象的唯一实例 private static PersistentObject _instance; void Awake() { // 检查是否已经存在实例 if (_instance != null && _instance != this) { // 如果已有实例,直接销毁当前新生成的重复对象 Destroy(gameObject); } else { // 如果没有实例,将自己设为唯一实例,并标记为不随场景销毁 _instance = this; DontDestroyOnLoad(gameObject); } } }
2. 代码逻辑解释
_instance是静态变量,整个游戏生命周期中只会有一份,用来记录第一个被创建的保留对象。Awake()是Unity对象初始化时最先调用的方法,适合在这一步做实例检查:- 当重新加载场景时,场景里的玩家对象会被重新创建,此时
_instance已经指向之前保留的那个对象,所以新生成的对象会被直接销毁。 - 如果是第一次加载场景,
_instance为空,就把当前对象设为实例,并通过DontDestroyOnLoad保留它。
- 当重新加载场景时,场景里的玩家对象会被重新创建,此时
3. 可选:场景加载后重置状态(比如玩家位置)
如果需要在场景加载完成后重置对象状态(比如把玩家放到出生点),可以添加场景加载事件监听,修改后的代码如下:
using UnityEngine; using UnityEngine.SceneManagement; public class PersistentObject : MonoBehaviour { private static PersistentObject _instance; void Awake() { if (_instance != null && _instance != this) { Destroy(gameObject); } else { _instance = this; DontDestroyOnLoad(gameObject); // 注册场景加载完成的回调事件 SceneManager.sceneLoaded += OnSceneLoaded; } } // 场景加载完成时自动调用 void OnSceneLoaded(Scene scene, LoadSceneMode mode) { // 示例:找到场景中的出生点,重置玩家位置 Transform spawnPoint = GameObject.Find("SpawnPoint").transform; if (spawnPoint != null) { transform.position = spawnPoint.position; } } void OnDestroy() { // 销毁对象时取消事件注册,避免内存泄漏 SceneManager.sceneLoaded -= OnSceneLoaded; } }
注意事项
- 每个需要跨场景保留的对象(比如全局UI、音效管理器)都可以挂这个脚本,确保各自只有一个实例。
- 不要手动在代码里重复实例化这些对象,让场景加载时自动生成即可,脚本会自动处理重复情况。
内容的提问来源于stack exchange,提问作者Business Cactus
相关产品推荐
相关产品推荐

