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

Godot EditorScript弹出EditorFileDialog失败报is_inside_tree错误

EditorScript中弹出EditorFileDialog失败问题

问题复现

在开发自定义JSON导入生成Tilemap功能时,编写如下EditorScript测试代码尝试弹出本地文件选择框:

tool
extends EditorScript
func _run():

    var fileDialog = EditorFileDialog.new()
    fileDialog.mode = EditorFileDialog.MODE_OPEN_FILE
    fileDialog.access = EditorFileDialog.ACCESS_FILESYSTEM  
    fileDialog.popup()
    ...

运行后无窗口弹出,调试器输出以下报错:

scene/gui/control.cpp:2154 - Condition "!is_inside_tree()" is true.
scene/2d/canvas_item.cpp:469 - Condition "!is_inside_tree()" is true. Returned: get_transform()
scene/2d/canvas_item.cpp:939 - Condition "!is_inside_tree()" is true. Returned: Rect2()
scene/gui/control.cpp:2128 - Condition "!is_inside_tree()" is true.
scene/gui/control.cpp:2128 - Condition "!is_inside_tree()" is true.
./scene/main/node.h:269 - Condition "!data.tree" is true. Returned: nullptr

报错原因

所有Godot的GUI控件必须被加入场景树后才能正常执行弹出、渲染、交互逻辑。直接通过new()创建的EditorFileDialog不属于任何现有节点的子节点,未进入场景树,调用popup()时引擎底层校验is_inside_tree()不通过,因此无法正常显示。

解决方案

方案1:手动创建对话框节点并挂载到编辑器根节点

这是自由度最高的方案,可自定义对话框的所有属性、过滤规则、按钮逻辑:

tool
extends EditorScript

func _run():
    var fileDialog = EditorFileDialog.new()
    # 基础配置
    fileDialog.mode = EditorFileDialog.MODE_OPEN_FILE
    fileDialog.access = EditorFileDialog.ACCESS_FILESYSTEM
    # 可选:添加JSON文件过滤
    fileDialog.add_filter("*.json ; JSON配置文件")
    # 将对话框加入编辑器场景树,这一步是核心
    EditorInterface.get_base_control().add_child(fileDialog)
    
    # 绑定文件选中回调
    fileDialog.file_selected.connect(func(file_path):
        # 此处编写读取JSON、生成Tilemap的业务逻辑
        print("选中文件路径:", file_path)
        # 逻辑执行完销毁临时对话框
        fileDialog.queue_free()
    )
    
    # 绑定窗口关闭回调,点击取消时也销毁节点避免残留
    fileDialog.popup_hide.connect(func():
        if is_instance_valid(fileDialog):
            fileDialog.queue_free()
    )
    
    # 居中弹出窗口,参数为窗口占屏幕比例
    fileDialog.popup_centered_ratio(0.75)

方案2:直接复用编辑器内置的全局文件对话框

如果不需要自定义复杂逻辑,可直接调用编辑器已有的文件对话框实例,省去手动创建、销毁节点的步骤:

tool
extends EditorScript

func _run():
    var dialog = EditorInterface.file_dialog
    # 先断开之前绑定的同信号,避免多次运行脚本导致重复触发
    if dialog.file_selected.is_connected(_on_file_selected):
        dialog.file_selected.disconnect(_on_file_selected)
    
    # 配置对话框参数
    dialog.mode = EditorFileDialog.MODE_OPEN_FILE
    dialog.access = EditorFileDialog.ACCESS_FILESYSTEM
    dialog.clear_filters()
    dialog.add_filter("*.json ; JSON配置文件")
    
    # 绑定选中回调
    dialog.file_selected.connect(_on_file_selected)
    # 弹出窗口
    dialog.popup_centered_ratio(0.75)

func _on_file_selected(file_path):
    # 此处编写读取JSON、生成Tilemap的业务逻辑
    print("选中文件路径:", file_path)
    # 用完断开信号避免后续其他功能触发该回调
    EditorInterface.file_dialog.file_selected.disconnect(_on_file_selected)

注意事项

  • 所有tool模式下在编辑器运行时创建的GUI控件,都必须挂载到编辑器场景树内的现有节点(通常取EditorInterface.get_base_control()作为根挂载点)才能正常显示
  • 临时创建的节点、绑定的信号要及时清理,避免多次运行脚本导致内存泄漏、信号重复触发等问题

内容的提问来源于stack exchange,提问作者macrico

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 15:39:25