Unity自定义编辑器serializedObject为空bug求助:update订阅未取消
解决EditorApplication.update订阅在预制体模式退出后持续调用的问题
嗨,我来帮你搞定这个头疼的问题!你的代码核心问题在于只订阅了EditorApplication.update事件,却没有在编辑器生命周期结束时取消订阅,再加上预制体模式切换时Unity编辑器对象的特殊生命周期变化,才导致了退出预制体后MyUpdate还在持续执行并报错的情况。
修复方案说明
我们需要做两件关键的事:
- 在编辑器的
OnDisable方法中取消订阅EditorApplication.update,这是Unity编辑器生命周期的标准做法——订阅和取消必须成对出现。 - 在
MyUpdate中增加更严谨的有效性检查,避免在对象失效后执行逻辑。
修改后的完整代码
using UnityEngine; using UnityEditor; using UnityEditor.SceneManagement; [CustomEditor(typeof(MyCustom))] [CanEditMultipleObjects()] public class MyCustomEditor : Editor { void MyUpdate() { // 首先检查编辑器本身是否有效、目标对象是否存在 if (!this || target == null || serializedObject == null) { // 如果已经失效,主动取消订阅并退出 EditorApplication.update -= MyUpdate; return; } // 额外检查:如果当前处于预制体模式,确保目标属于当前预制体阶段 var currentPrefabStage = PrefabStageUtility.GetCurrentPrefabStage(); if (currentPrefabStage != null && !currentPrefabStage.IsPartOfPrefabContents(target.gameObject)) { return; } // 这里放你的业务逻辑 // My code stuff } void OnEnable() { // 订阅update事件,无需额外标记,因为OnEnable和OnDisable是成对调用的 EditorApplication.update += MyUpdate; } void OnDisable() { // 必须在这里取消订阅,确保编辑器销毁/停用时移除委托 EditorApplication.update -= MyUpdate; } }
关键修复点解释
- OnDisable中取消订阅:当你退出预制体模式、取消选中对象,或者关闭Inspector面板时,Unity会调用编辑器的
OnDisable方法,此时移除MyUpdate委托,就能彻底停止后续的调用。 - 多重有效性检查:在
MyUpdate开头增加的检查,是为了应对一些极端情况(比如Unity没有及时调用OnDisable的边缘场景),确保失效后不会执行逻辑,还能主动取消订阅。 - 预制体阶段检查:通过
PrefabStageUtility判断当前是否在预制体模式,以及目标对象是否属于当前预制体内容,避免跨阶段的无效操作。
为什么你的原代码会出问题?
你原来的代码只在OnEnable中订阅事件,却没有对应的取消逻辑。当你退出预制体模式时,附加在子物体上的编辑器实例其实已经被Unity标记为失效,但EditorApplication.update的委托还挂着,导致MyUpdate继续执行,此时serializedObject已经变成null,自然会不断报错。
内容的提问来源于stack exchange,提问作者Ruslan Plastun
相关产品推荐
相关产品推荐

