Unity NewGraph工具特定Playmode设置下MonoGraphModel报错问题
解决方案:MonoGraphModel在Play Mode切换时的空引用错误及编辑器初始化问题
核心问题分析
错误根源是Disable Domain Reload + 不Disable Scene Reload的PlayMode设置组合下,MonoGraphModel绑定的GameObject在模式切换时处于“半销毁/半初始化”状态,NewGraph的UI调度器仍在尝试访问已失效的SerializedObject,导致空引用。而ScriptableGraphModel基于ScriptableObject,生命周期不受Scene对象影响,因此无此问题。
分步修复方案
1. 拦截GraphWindow的PlayMode状态回调,提前清理资源
修改LogPlayModeState方法,在进入PlayMode前强制关闭GraphWindow并释放引用,避免UI调度器后续访问无效对象:
public static void LogPlayModeState(PlayModeStateChange state) { switch(state) { case PlayModeStateChange.ExitingEditMode: // 进入PlayMode前强制关闭窗口,清理所有调度任务 window?.Close(); window = null; break; case PlayModeStateChange.EnteredEditMode: // 回到编辑模式后重新加载窗口和图表 LoadGraph(); break; case PlayModeStateChange.EnteredPlayMode: // 仅在需要时重新初始化(如果保留窗口的场景对象) if(!EditorSettings.enterPlayModeOptionsEnabled || EditorSettings.enterPlayModeOptions.HasFlag(EnterPlayModeOptions.DisableSceneReload)) { window = GraphWindow.OpenWindow(); window.graphController?.Reload(); } break; case PlayModeStateChange.ExitingPlayMode: // 退出PlayMode前确保序列化完成 window?.graphController?.EnsureSerialization(); break; } }
2. 修复MonoGraphModel的SerializedObject创建逻辑
在MonoGraphModel.cs的CreateSerializedObject方法中添加空引用检查,避免传入null对象创建SerializedObject:
protected override SerializedObject CreateSerializedObject() { if(this == null || gameObject == null) { Debug.LogWarning("MonoGraphModel or its GameObject is null, cannot create SerializedObject"); return null; } return base.CreateSerializedObject(gameObject, "_graphData"); }
同时修改get_BaseObject属性,增加空值判断:
public override object BaseObject { get { if(_serializedObject == null) { _serializedObject = CreateSerializedObject(); } return _serializedObject?.targetObject; } }
3. 确保节点编辑器在PlayMode下正确初始化
在GraphController.cs的Reload方法中,增加对PlayMode状态的判断,仅在合适时机重新初始化节点编辑器:
public void Reload() { if(EditorApplication.isPlaying && EditorSettings.enterPlayModeOptionsEnabled && !EditorSettings.enterPlayModeOptions.HasFlag(EnterPlayModeOptions.DisableSceneReload)) { // 在保留Scene的PlayMode下,直接复用现有MonoGraphModel实例 var monoGraph = graphModel as MonoGraphModel; if(monoGraph != null && monoGraph.gameObject != null) { InitializeGraph(monoGraph); } return; } // 原有重载逻辑 // ... }
4. 注册回调的正确时机
确保回调在编辑器启动时注册,避免重复注册:
[InitializeOnLoadMethod] private static void Initialize() { EditorApplication.playModeStateChanged -= LogPlayModeState; EditorApplication.playModeStateChanged += LogPlayModeState; }
无需使用RuntimeInitializeOnLoadMethod,这是编辑器逻辑,InitializeOnLoadMethod更适配场景。
验证步骤
- 启用Disable Domain Reload并关闭Disable Scene Reload的PlayMode设置
- 打开GraphWindow并选中绑定MonoGraphModel的GameObject
- 进入PlayMode,确认无空引用错误
- 验证节点编辑器正常显示并初始化
- 退出PlayMode后,确认图表数据正常保留
内容的提问来源于stack exchange,提问作者Martin
相关产品推荐
相关产品推荐

