
示例工程【免费下载链接】godot-demo-projectsDemonstration and Template Projects项目地址https://gitcode.com/GitHub_Trending/go/godot-demo-projects点击查看免费下载本指南以 godot-demo-projects 仓库中的 Material Creator Plugin Demoplugins/addons/material_creator为对象完整讲解一个可写可读可导入的自定义材质插件是如何炼成的在编辑器里添加自定义 Dock、定义可序列化的自定义 Resource 类型并通过EditorImportPlugin与ResourceFormatLoader/ResourceFormatSaver两条互斥管线实现资源的导入、加载、保存与导出。读完本文你将掌握在真实项目中为任意自定义文件格式搭建编辑器集成的完整思路与可复制的代码骨架。插件概览一个傻乎乎但五脏俱全的材质工具Material Creator 是一个运行在 Godot 编辑器内的插件示例其定位在 material_plugin.gd 的注释中说得非常直白允许你从一个自定义 Dock 制作极其简单的材质并把它应用到网格、保存到文件、从文件加载、从文件导入等。插件元信息记录在 plugin.cfg 中[plugin] nameMaterial Creator Plugin Demo descriptionLoads and saves a 3D Material from an external text file authorAaron Franke, TwistedTwigleg, Šarūnas Ramonas version1.0 scriptmaterial_plugin.gd整个插件演示了三件事这也是理解其源码结构的钥匙自定义编辑器 DockDock 由Control节点组成运行在编辑器进程中任何行为都必须通过tool脚本驱动自定义 Resource 类型SillyMaterialResource附带完整的序列化、反序列化与类型转换逻辑编辑器集成提供加载、保存、导入三类编辑器类并支持可选的导入定制import customization。目录结构上importers/ 存放两个EditorImportPlugin子类load_and_save/ 存放自定义加载器与保存器examples/ 存放五种不同行为模式的示例文件Dock 本体由 material_dock.tscn 与 material_creator.gd 构成。Importing vs Loading两条互斥的资源管线README 用一整节篇幅强调了本插件最重要的设计结论同一文件扩展名上导入Import与加载Load两条路径是互斥的一个文件扩展名在同一时刻只能由一种机制接管。本插件故意用两个不同的扩展名同时展示两种机制importers/ 中的EditorImportPlugin负责定制文件如何被导入为 Godot Resource导入产物类型可不同、可带导入设置。被导入的文件旁边会生成.import文件。load_and_save/ 中的ResourceFormatLoader与ResourceFormatSaver负责在检查器里直接编辑文件并保存回去。Resource 文件旁边会生成.uid文件。那么实际项目里该怎么选核心判断标准是你把这个文件当作外部源资产还是Godot 内部资源。外部源资产 → 用EditorImportPlugin。例如 glTF 由 Blender 生成PNG 由图像编辑器生成Godot 需要把它们转换如 PNG 转成 VRAM 压缩的.ctex成内部格式且导入过程可以定制预设、选项导入产物只读。Godot 原生格式 → 用ResourceFormatLoader。例如.tres、.tscn天生就是要被 Godot 直接编辑的加载器让数据可被修改并保存回文件。选择好方向后创建相应类的子类、覆写回调函数并在插件的*_plugin.gd脚本中注册即可。仓库里另有一个更精简的对照示例 simple_import_plugin而更全面的参考是 Godot 源码中的 GLTF 模块。自定义 Resource 类型SillyMaterialResource一切序列化、加载、导入逻辑都围绕 silly_material_resource.gd 中的SillyMaterialResource展开。它继承自Resource用export声明三个可在检查器编辑、可被保存/加载系统序列化的属性export var albedo_color: Color Color.BLACK export var metallic_strength: float 0.0 export var roughness_strength: float 0.0类内封装了 6 个关键方法构成了编辑器类只是轻量包装器的设计核心这些函数放在 Resource 类上是为了同时支持运行时的导入导出方法作用from_json_dictionary(json_dictionary)静态方法从 JSON 解析出的 Dictionary 读取数据生成新的SillyMaterialResourceto_json_dictionary()把当前数据转为 Dictionary用于保存为 JSONfrom_material(mat)静态方法从StandardMaterial3D复制 albedo/metallic/roughness 数据to_material()用当前数据生成一个新的StandardMaterial3Dread_from_file(path)包装from_json_dictionary用FileAccess打开文件并解析 JSONwrite_to_file(path)包装to_json_dictionary把 JSON 字符串写入文件其文件格式是极简的 JSON例如 yellow.silly_mat_importable 的真实内容{albedo_color:[0.933333337306976,0.933333337306976,0.0666666701436043],metallic_strength:0.65,roughness_strength:0.35}注意read_from_file与write_to_file使用的是FileAccess直接读写文本文件因此不依赖res://目录对项目外部的文件也有效——这正是运行时直接导入/导出按钮可行性的来源。源码注释也提醒真实导入器面对任意用户数据时应当检查键是否存在、数组长度是否为 3、值是否为数字等示例代码为简洁起见省略了这些健壮性检查。管线一ResourceFormatLoader / ResourceFormatSaver可写回load_and_save/ 目录下的两个类接管.silly_mat_loadable扩展名实现在检查器中编辑并保存回去的可写管线。SillyMatFormatLoadermaterial_format_loader.gd覆写了 4 个回调func _get_recognized_extensions() - PackedStringArray: return PackedStringArray([silly_mat_loadable]) func _get_resource_type(path: String) - String: if path.get_extension() silly_mat_loadable: return SillyMaterialResource return func _handles_type(type_name: StringName) - bool: return type_name SillyMaterialResource func _load(path: String, original_path: String, use_sub_threads: bool, cache_mode: int) - Variant: return SillyMaterialResource.read_from_file(original_path)SillyMatFormatSavermaterial_format_saver.gd则对应提供扩展名声明、类型识别与保存回调_save最终委托给write_to_filefunc _save(resource: Resource, path: String, flags: int) - Error: var mat_res: SillyMaterialResource resource as SillyMaterialResource if mat_res null: return ERR_INVALID_DATA return mat_res.write_to_file(path)该管线的特点是加载后数据可修改并写回原文件但不可配置——没有 Import 面板里那种可调选项且同一扩展名只允许一个加载器存在。加载器注册进编辑器后用ResourceLoader.load()即可返回一个可写的SillyMaterialResource。管线二EditorImportPlugin可配置、只读importers/ 下的两个类接管.silly_mat_importable扩展名且同一个扩展名可以由多个导入器共存用户在 Import 面板里选择用哪个、配置什么参数。import_silly_material.gd导入为SillyMaterialResource可见名 Silly Material Resourceimport_standard_material_3d.gd导入为StandardMaterial3D可见名 Standard Material 3D演示了导入器可以把自定义文件转换成 Godot 原生数据类型。两个类共享同一套导入选项——make_more_red默认false展示导入设置如何在导入时修改数据func _get_import_options(_path: String, preset: int) - Array[Dictionary]: var ret: Array[Dictionary] [ { name: make_more_red, default_value: false, } ] return ret func _import(source_file: String, save_path: String, options: Dictionary, r_platform_variants: Array[String], r_gen_files: Array[String]) - Error: var silly_mat_res : SillyMaterialResource.read_from_file(source_file) if options.has(make_more_red) and options[make_more_red]: silly_mat_res.albedo_color silly_mat_res.albedo_color.lerp(Color.RED, 0.5) var imported_path: String %s.%s % [save_path, _get_save_extension()] return ResourceSaver.save(silly_mat_res, imported_path)两处细节值得注意_get_resource_type()返回的类型必须是 Godot 原生类型不能是 GDScript 自定义类型因此SillyMaterialResource导入器返回Resource而非类名导入产物以res://.godot/imported/something.res的形式保存文件名带内容哈希以 yellow_tinted_red.silly_mat_importable.import 为例其[remap]段记录了importerdemos.silly_material_importable.silly_material_resource、typeResource、目标路径res://.godot/imported/yellow_tinted_red.silly_mat_importable-d6610364b07d235546934af33df4be98.res[params]段则保存了make_more_redtrue的导入设置。导入后的文件只读不能在检查器中编辑编辑器 Dock六个按钮的完整行为Dock 本体是Panel场景material_dock.tscn包含一个VBoxContainer自上而下是 Albedo 颜色选择器、Metallic/Roughness 滑块HSlider范围 0–1、步长 0.05、分隔线以及 6 个按钮每个按钮都对应 material_creator.gd 中的一个槽函数信号在 tscn 末尾的[connection]中一一绑定按钮行为底层实现Apply Material把当前材质应用到编辑器中所有选中的MeshInstance3D节点通过editor_interface.get_selection()拿到选中节点逐个调用set_surface_override_material(0, new_material)无选中节点或选中节点不含MeshInstance3D时报错Save Material (ResourceFormatSaver)用自定义 saver 存为.silly_mat_loadable或用 Godot 内建ResourceFormatSaverText存为.tres_save_or_export_file扩展名是tres或项目内silly_mat_loadable时走ResourceSaver.save否则直接write_to_fileExport Material (directly at runtime)用SillyMaterialResource的函数导出为.silly_mat_*文件对项目外路径同样有效保存对话框access 2可脱离编辑器在运行时完成Load Material (ResourceFormatLoader)用自定义 loader 加载.silly_mat_loadable或用 Godot 内建ResourceFormatLoaderText加载.tresload_file_resource_loaderResourceLoader.load()后把数据灌回 Dock 的控件Load Imported Material (EditorImportPlugin)加载已由导入器导入的.silly_mat_importable实际读取的是.godot/imported/下的导入产物含哈希的.res数据只读Import Material (directly at runtime)直接从源文件做一次按需导入load_file_directly调用SillyMaterialResource.read_from_file()跳过导入设置、支持res://外文件、可在运行时执行Dock 脚本中还有两个面向编辑器体验的细节保存/导出前用DirAccess.make_dir_recursive_absolute确保目录存在成功后调用editor_interface.get_resource_filesystem().scan()通知编辑器刷新文件系统_ready里还通过RenderingServer.canvas_item_set_clip对自身画布裁剪。Dock 场景的尺寸则会乘以EditorInterface.get_editor_scale()以适配编辑器缩放。示例文件五种行为模式逐一对照examples/ 下的 5 个文件把两条管线的所有行为模式浓缩在一起blue.tres直接使用 Godot 内建.tres格式保存SillyMaterialResource不经过任何自定义 loader/saver 与导入导出逻辑——.tres对所有 Resource 类型通用可在检查器编辑并保存回去。cyan.silly_mat_loadable含.uid以自定义格式存储SillyMaterialResource由自定义ResourceFormatSaver写出、自定义ResourceFormatLoader读回可在检查器编辑并保存回去。green_as_standard_mat.silly_mat_importable以自定义格式存储由自定义导入/导出逻辑导入为StandardMaterial3D——演示导入器可以把自定义文件转换成 Godot 能直接使用的数据。导入后只读。yellow.silly_mat_importable以自定义格式存储导入为SillyMaterialResource导入后只读。yellow_tinted_red.silly_mat_importable与yellow源文件内容完全相同但对应的.import文件里设置了make_more_redtrue导入时 albedo 向红色插值 50%于是材质显示为橙色而非黄色——这正是导入设置可在导入时修改数据的实证。最后这个文件还精妙地演示了走导入流程与绕过导入流程的差异用编辑器的 Load Imported Material (EditorImportPlugin) 或 GDScript 的ResourceLoader.load()会得到带红色调、albedo 为橙色的导入版本而用 Import Material (directly at runtime) 或SillyMaterialResource.read_from_file()则会直接读取源文件、忽略导入过程albedo 保持黄色。前者只在编辑器导入流程内可用后者在编辑器和运行时都可用。插件注册与生命周期material_plugin.gd 的编排所有组件最终在 material_plugin.gdtool继承EditorPlugin中被组装。_enter_tree()依次完成四件事func _enter_tree() - void: # Set up the loader and saver. ResourceLoader.add_resource_format_loader(_silly_mat_loader) ResourceSaver.add_resource_format_saver(_silly_mat_saver) # Set up the importers. add_import_plugin(_import_as_silly_mat_res) add_import_plugin(_import_as_standard_mat) # Set up the silly material creator dock. const dock_scene: PackedScene preload(res://addons/material_creator/editor/material_dock.tscn) _material_creator_dock dock_scene.instantiate() _material_creator_dock.editor_interface get_editor_interface() var dock_scale: float EditorInterface.get_editor_scale() * 0.85 _material_creator_dock.custom_minimum_size * dock_scale for child in _material_creator_dock.find_children(*, Control): child.custom_minimum_size * dock_scale add_control_to_dock(DOCK_SLOT_LEFT_UL, _material_creator_dock)依次为注册加载器与保存器 → 注册两个导入器 → 实例化 Dock 场景并把EditorInterface注入其中Dock 脚本通过它访问选中节点、文件系统→ 按编辑器缩放调整控件尺寸后停靠到左侧上方的 Dock 槽位DOCK_SLOT_LEFT_UL。_exit_tree()则按相反顺序全部反注册/移除保证插件禁用时不留残留。选型总结在真实项目中如何决策结合本文全部源码证据实战选型可以归纳为一张决策表文件由外部工具生成、需要格式转换、需要可配置导入参数 →EditorImportPlugin可多个并存Import 面板选择/配置产物只读文件是 Godot 原生编辑对象、需要检查器内编辑并写回 →ResourceFormatLoaderResourceFormatSaver可写回但同一扩展名仅一个且不可配置需要脱离编辑器在运行时读写文件含res://之外→ 把序列化逻辑放在 Resource 类本身如read_from_file/write_to_file让编辑器类成为轻量包装器记住互斥铁律同一扩展名同一时刻只能选一条管线本插件正是用.silly_mat_loadable与.silly_mat_importable两个扩展名在同一个插件里并存演示了两条路径。赞分享示例工程【免费下载链接】godot-demo-projectsDemonstration and Template Projects项目地址https://gitcode.com/GitHub_Trending/go/godot-demo-projects点击查看免费下载相关推荐Godot 编辑器插件开发全解自定义节点、主屏幕、自定义 Dock 与自定义导入基于 godot-demo-projects 的 Plugin DemosGodot 编辑器插件开发全解自定义节点、主屏幕、自定义 Dock 与自定义导入基于 godot demo projects 的 Plugin Demos示例工程Theatre动画曲线编辑器自定义曲线的导入导出Theatre动画曲线编辑器自定义曲线的导入导出 动画曲线是决定界面元素运动节奏的核心无论是平滑的过渡效果还是富有弹性的交互反馈都离不开精细的曲线控制。T前端Godot 主屏幕插件Main Screen Plugin开发实战为编辑器添加自定义工作区Godot 主屏幕插件Main Screen Plugin开发实战为编辑器添加自定义工作区 导读 本文基于 godot demo projects 仓库中示例工程上一篇3DTilesRendererJS 项目常见问题解决方案下一篇GNOME Shell扩展——Blur my Shell常见问题解决方案创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考