← Back to Blog tutorials

Godot 4 EditorImportPlugin: custom GLB import pipelines

By BitSoul Team6/3/2026Updated 8/7/20264 min read69 views
Godot 4 EditorImportPlugin: custom GLB import pipelines

Building a custom GLB import pipeline in Godot 4 puts you in full control — automatic LOD generation, collision meshes, shadow proxies, and material overrides applied the moment a file lands in your project. EditorImportPlugin is the hook that makes it possible.

What EditorImportPlugin does and when to use it

Godot's built-in GLB importer handles most assets well, but it runs identically on every file. When you have 747 assets from a source like the BitSoul marketplace and need consistent treatment — stripped UV2 channels, forced double-sided materials, or named collision nodes — writing a custom importer pays for itself on the first batch import.

`EditorImportPlugin` is a GDScript (or C#) class that registers itself with the editor. It declares the file extensions it handles, a priority value that overrides the default importer, and a `_import()` method that receives the source path and writes to a `.godot`-internal resource file. The four methods you must implement: `_get_importer_name()` returns a unique reverse-domain string; `_get_recognized_extensions()` returns `["glb"]`; `_get_priority()` returns a float above 1.0 to supersede the built-in GLB importer; `_get_import_order()` returns 0 for most cases.

```gdscript
@tool
extends EditorImportPlugin

func _get_importer_name(): return "com.mystudio.glb_game_ready"
func _get_recognized_extensions(): return ["glb"]
func _get_priority() -> float: return 2.0 # > 1.0 overrides the default importer
func _get_import_order() -> int: return 0
```

Place this script in `addons/glb_importer/` alongside a `plugin.cfg` and enable it in Project → Project Settings → Plugins.

What EditorImportPlugin does and when to use it — illustrated

Implementing LOD generation in _import()

The `_import()` method receives the source GLB path and an `options` dictionary from `_get_import_options()`. Load the scene via `GLTFDocument`, walk every `MeshInstance3D` with a recursive helper (`_get_all_children(scene)`), then call `generate_lods()` on each `ImporterMesh`. Always call `scene.queue_free()` after packing — the editor does not garbage-collect the generated scene automatically.

```gdscript
func _import(source_file, save_path, options, platform_variants, gen_files) -> Error:
var doc := GLTFDocument.new()
var state := GLTFState.new()
var err := doc.append_from_file(source_file, state)
if err != OK: return err

var scene := doc.generate_scene(state)
for node in _get_all_children(scene):
if node is MeshInstance3D:
var im := node.mesh.get_importable_mesh()
if im:
im.generate_lods(options.get("lod_normal_merge_angle", 25.0),
options.get("lod_normal_split_angle", 60.0), [])
node.mesh = im.get_mesh()

var packed := PackedScene.new()
packed.pack(scene)
scene.queue_free()
return ResourceSaver.save(packed, "%s.%s" % [save_path, _get_save_extension()])
```

`generate_lods()` takes merge angle, split angle, and an optional LOD ratio array — pass `[]` to let Godot choose automatically (typically 0.25, 0.1, 0.04). `get_importable_mesh()` returns null for meshes that weren't imported as `ImporterMesh`, so always check before calling.

Adding automatic collision meshes

After the LOD loop, add `StaticBody3D` collision for each prop mesh: create a `StaticBody3D`, add a child `CollisionShape3D` with `shape = node.mesh.create_convex_shape(true, true)` (both flags clean and simplify the hull), set `.owner = scene` on both nodes, then call `node.add_child(body)`. For concave meshes — stairs, hollow props — use `create_trimesh_shape()` instead; it's more accurate but more expensive at runtime.

Declaring import options for per-asset control

Return import options from `_get_import_options(_path, _preset_index)` as an `Array[Dictionary]`, each entry with `name` and `default_value` keys. They appear as editable fields in the Import dock, letting artists override settings per file without touching code. Commit `.import` sidecar files to version control so teammates get identical results.

| Option | Default | Effect |
|------|--------|--------|
| `generate_collision` | `true` | Adds `StaticBody3D` + hull shape |
| `lod_normal_merge_angle` | `25.0` | Merge angle for LOD generation |
| `lod_normal_split_angle` | `60.0` | Split angle for LOD generation |
| `force_double_sided` | `false` | Disables back-face culling on all surfaces |
| `shadow_proxy_lod` | `2` | Which LOD level is used as shadow caster |

Declaring import options for per-asset control — illustrated

Workflow checklist for shipping a custom importer

| Step | Action | Gotcha |
|------|--------|--------|
| Register plugin | Add `plugin.cfg`, enable in Project Settings | Priority must be > 1.0 to override default GLB importer |
| Define options | Return typed dicts from `_get_import_options()` | Missing `type` key causes silent failures in older 4.x builds |
| LOD generation | Call `generate_lods()` on `ImporterMesh`, reassign `.mesh` | Only works if the original mesh was imported as `ImporterMesh`; check with `get_importable_mesh()` |
| Collision | Use `create_convex_shape(true, true)` for props | Concave meshes need `create_trimesh_shape()` — more expensive at runtime |
| Re-import trigger | Edit `.import` file or call `EditorFileSystem.reimport_files()` | Godot does not auto-reimport after plugin code changes |
| Version control | Commit `.import` sidecars | Without them, collaborators fall back to default importer settings |

The BitSoul marketplace ships assets as clean GLB with consistent naming — ideal input for a pipeline like this, since node names are predictable and the plugin can branch on them (e.g., nodes prefixed `UCX_` get collision-only treatment, matching Unreal conventions).

Automating import with `EditorImportPlugin` turns asset integration from a per-file chore into a one-time engineering task. Write it once, import 500 assets the right way every time.

---

*This post is part of the Ultimate Guide to Free 3D Game Assets — BitSoul's complete reference for formats, texturing, rigging, optimization, and engine integration.*

Tags: tutorials game-assets 3d-models optimization godot workflow glb

Skip the modelling — download it instead

A free BitSoul account gets you 2 game-ready models every month plus 25 AI Engine credits to generate one of your own, no card required. Clean topology, PBR textures, and GLB downloads that drop straight into Unreal, Unity, Godot or Blender — plus OBJ and 3D-printable STL export.

Create a free account → Browse 846 models