You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 04:36:03