Unity单例脚本重启编辑器后需重挂载以规避空引用异常
问题分析与解决方案
你的空引用问题根源有两个:
- 单例逻辑不完整:当前代码仅处理了重复实例的销毁,但未确保单例对象在场景切换时不被销毁,也没处理Unity编辑器中静态变量的残留引用。
- 编辑器静态变量残留:Unity编辑器停止运行后,静态变量不会自动清空,下次启动时
Timing可能指向已销毁的对象,导致访问Bpm时报错。
修正后的单例代码
using UnityEngine; public class Conductor : MonoBehaviour { public static Conductor Timing { get; private set; } [SerializeField] private double bpm; private void Awake() { // 处理重复实例:若已有单例,销毁当前对象 if (Timing != null) { Destroy(gameObject); return; } Timing = this; // 确保对象在场景切换时不被销毁 DontDestroyOnLoad(gameObject); } // 对象销毁时重置静态变量,避免残留无效引用 private void OnDestroy() { if (Timing == this) { Timing = null; } } // 游戏启动前重置静态变量,解决编辑器残留问题 [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)] private static void ResetSingleton() { Timing = null; } public double Bpm { get => bpm; set => bpm = value; } }
关键修改说明
DontDestroyOnLoad(gameObject):让单例对象在场景切换时保留,避免因场景加载导致实例销毁,Timing变为空引用。OnDestroy重置静态变量:单例对象被销毁时,将Timing置空,防止后续引用已销毁的无效对象。RuntimeInitializeOnLoadMethod:在游戏启动前强制重置静态变量,解决Unity编辑器停止运行后静态变量残留的问题,确保每次启动时Timing处于初始状态。
调用注意事项
确保场景中仅存在一个挂载Conductor的游戏对象,避免重复实例被销毁的情况。调用时可额外增加空判断,防止极端场景报错:
if (Conductor.Timing != null) { var currentBpm = Conductor.Timing.Bpm; // 后续业务逻辑 }
内容的提问来源于stack exchange,提问作者maddogedge
相关产品推荐
相关产品推荐

