unity DontDestroyOnLoad的坑,以及如何绕过

在使用DontDestroyOnLoad的时候,Scene A到B,对象a没有被销毁,从Scene B再返回A,这时候在加载SceneA的过程中,对象a又被重新加载了一次,这时候,我们怎么办呢?

可以用unity自带的数据存储功能,存储一个变量作为标记,起到一个开关的功能,只要进去了一次,以后都进不去了,具体代码就不贴了

### Unity 中 `DontDestroyOnLoad` 的用法及常见问题 在 Unity 中,`DontDestroyOnLoad` 是一个非常重要的方法,用于确保某些游戏对象(GameObject)在场景切换时不会被销毁。默认情况下,当从一个场景切换到另一个场景时,所有当前场景中的对象都会被销毁,并加载新场景中的对象。然而,有些对象可能需要在整个游戏过程中保持存在,例如全局管理器、背景音乐播放器等。这时可以使用 `DontDestroyOnLoad` 方法来实现这一需求[^1]。 以下是关于 `DontDestroyOnLoad` 的详细说明和示例代码: #### 1. 基本用法 通过调用 `Object.DontDestroyOnLoad` 方法,可以将指定的游戏对象或组件标记为“不随场景销毁”。以下是一个简单的示例,展示如何使用该方法保留一个全局管理器对象: ```csharp using UnityEngine; public class PersistentManager : MonoBehaviour { void Start() { // 确保此对象在场景切换时不被销毁 DontDestroyOnLoad(gameObject); } } ``` 在此示例中,`PersistentManager` 对象将在整个游戏生命周期内保持存在,即使场景发生切换也不会被销毁。 #### 2. 注意事项 - **避免重复实例化**:如果多个场景中都有类似的持久化对象,可能会导致重复实例化的问题。为了解决这个问题,通常会结合单例模式使用 `DontDestroyOnLoad`。以下是一个改进的单例实现示例: ```csharp using UnityEngine; public class SingletonManager : MonoBehaviour { private static SingletonManager _instance; public static SingletonManager Instance { get { if (_instance == null) { _instance = FindObjectOfType<SingletonManager>(); if (_instance == null) { GameObject obj = new GameObject("SingletonManager"); _instance = obj.AddComponent<SingletonManager>(); } } return _instance; } } void Awake() { if (_instance == null) { _instance = this; DontDestroyOnLoad(gameObject); } else if (_instance != this) { Destroy(gameObject); } } } ``` 在这个例子中,`SingletonManager` 类确保了只有唯一的一个实例存在,并且该实例在场景切换时不会被销毁[^2]。 #### 3. 常见问题与解决方案 - **内存泄漏问题**:如果使用 `DontDestroyOnLoad` 的对象引用了大量资源(如纹理、音频等),并且这些资源没有被正确释放,可能会导致内存占用过高。因此,在设计持久化对象时,应尽量减少对大资源的直接引用[^1]。 - **跨场景通信问题**:有时需要在不同场景之间传递数据或事件通知。可以结合消息系统(如 `CSharpMessenger Extended` 或自定义的通知中心)来实现跨场景通信。例如,使用以下方式发送通知: ```csharp NotificationCenter.DefaultCenter().PostNotification(this, "SceneChanged"); ``` 需要注意的是,如果消息接收方已经被销毁,可能会引发 `MissingReferenceException` 异常。可以通过捕获异常或检查对象状态来避免此类问题[^3]。 #### 4. 示例场景 假设有一个背景音乐管理器,希望在所有场景中持续播放音乐,可以这样实现: ```csharp using UnityEngine; public class BackgroundMusicManager : MonoBehaviour { private static BackgroundMusicManager _instance; public static BackgroundMusicManager Instance { get { return _instance; } } void Awake() { if (_instance == null) { _instance = this; DontDestroyOnLoad(gameObject); } else if (_instance != this) { Destroy(gameObject); } } public void PlayMusic(AudioClip clip) { GetComponent<AudioSource>().clip = clip; GetComponent<AudioSource>().Play(); } } ``` 在这个例子中,`BackgroundMusicManager` 对象会在所有场景中保持存在,并提供播放背景音乐的功能[^1]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值