
Publisher
gleeson
LDtk Importer 2D
The most fully-featured, up-to-date LDtk Importer Plugin for Godot 4. Leverage LDTk's powerful editor to quickly create your own 2D levels and maps. - Imports .ldtk files into Scenes to use in your project. - Fast, automatically reloads on saved changes. - Use Post-Import scripts to customise the resulting scene More extensive documentation can be found on Github.
This plugin has been mirrored from the Godot Asset Library.
The plugin author is in no way affiliated with Gadget.
If you are the author of this plugin and would like this mirror removed, please contact support@gadgetgodot.com.
Godot LDtk Importer
LDtk importer plugin for Godot 4

Quickstart
- Download the latest release
- Unpack
/ldtk-importer/into the/addons/folder in your Godot project. - Enable this plugin in
Project > Project Settings > Plugins .ldtkfiles can now be opened in the Editor!
✨ Features
🌏 World
- Imports '.ldtk' files as Scenes
- Supports separating Levels by WorldDepth
🏔️ Level
- Imports level background images
- Parses Level Fields into Godot types
- Supports external levels
📄 Layer
- Generates TileMaps from all LDtk tile layer types (Tiles, IntGrid, AutoLayer)
- Supports LDtk Tilemap layers of different grid sizes
- EntityLayers store an array of Entities, to be handled later (by Placeholders or a Post-Import script)
🧱 Tilesets
- Generates Atlases from LDtk Tilesets
- Supports flipped tiles
- Supports importing as CanvasTextures, allowing for usage of normal maps.
- Allows for further editing of TileSets in the Editor, preserving changes (Physics Layers, Render Layers, etc.)
- Supports Tile Custom Data
🐸 Entities
- Creates placeholder
LDTKEntitynodes. - Parses Entity Fields into Godot types
- Handles EntityRefs
🚩 Import Options

With the .ldtk file selected in FileViewer, go to the Import dock to view the following import options:
- World
- Separate World Layers: *Group levels into
LDTKWorldLayernodes, sorted byworldDepth.
- Separate World Layers: *Group levels into
- Tileset
- Force Tileset Reimport: Ignore existing TileSets and generate new ones.
- Tileset Custom Data: Add tile custom data (see Tile Custom Data)
- Atlas Texture Type: CompressedTexture2D or CanvasTexture
- Entity
- Use Entity Placeholders: Create
LDTKEntitynodes that emulate entities inside LDTK.
- Use Entity Placeholders: Create
- Post Import
- Tileset Post Import: Attach script (see Post-Import)
- Entity Post Import: Attach script (see Post-Import)
- Level Post Import: Attach script (see Post-Import)
- World Post Import: Attach script (see Post-Import)
🧩 Tile Custom Data
LDtk allows you to add custom data to individual tiles in any given tileset.
This data can either be numbers, text, JSON, XML, etc. Basically, any tile related info you would like to pass to your game engine.
If the import option Tileset Custom Data is selected, a Custom Data Layer is added and the data is stored on the tile as a String. If you need to further parse your tile data, write a Tileset Post-Import script.
🔧 Post-Import
You can hook up custom scripts that run during importing that further modify the resulting Scene/Resource.
Currently, there are four points where a post-import script can be inserted, in order of execution:
- TileSet: supplies an Array of generated TileSets
- Entity: supplies a LDTKEntityLayer containing the layer definition and entities.
- Level: supplies a LDTKLevel node containing TileMaps, Backgrounds(Sprite2D) and LDTKEntityLayer nodes.
- World: supplies the LDTKWorld containing all LDTKLevel nodes.
Example post-import scripts are included to cover common use cases; feel free to edit/expand on them to suit your project.
Post-Import: Tilesets
@tool
func post_import(tilesets: Dictionary) -> Dictionary:
# Behaviour goes here
return tilesets
Post-Import: Entity Layer
@tool
func post_import(entity_layer: LDTKEntityLayer) -> LDTKEntityLayer:
var definition: Dictionary = entity_layer.definition
var entities: Array = entity_layer.entities
for entity in entities:
# Perform operations here
pass
return entity_layer
Post-Import: Level
@tool
func post_import(level: LDTKLevel) -> LDTKLevel:
# Behaviour goes here
return level
Post-Import: World
@tool
func post_import(world: LDTKWorld) -> LDTKWorld:
# Behaviour goes here
return world
❓FAQ
How do I add tileset collisions?
While it is possible to add tileset collisions via a post-import script, this plugin is designed so that it is easy to manually edit the generated TileSets inside the project directly - reimporting the LDtk file will preserve these changes.
- Open the generated TileSet (e.g.
tilesets/tileset16x16.res) - In the Inspector, add a Physics Layer
- In the
TileSetpane, select theTileSetAtlasSourceand go to theSelectview. - Open the
Physicssubmenu and select the createdPhysics Layer. - Add collision polygons to each individual tile as necessary
TIP: A quick way to do this is to click+drag to select multiple tiles, and press F to use the default tile shape.
How do I add tilemap normals?
- Under
Import Options, make sure you have selectedAtlas Texture TypetoCanvas Texture - Open the generated TileSet (e.g.
tilesets/tileset16x16.res) - In the
Tilesetpane, select theTileSetAtlasSourcego to theSetupview - Select
Texture, and add the corresponding normal map.
How do EntityRefs work when I want to use my own nodes?
This was quite tricky to get right, and still needs some testing! I might expand this into its own section, but it's probably best if I explain how these are currently handled by the importer.
LDTK uses instance ids to refer to unique instances of levels, entities, etc. They look this:
{
"iid": "c27f1f10-3b70-11ee-8b24-732c4cff2bf2"
}
There are two things to consider when converting the JSON into a scene:
- The node that the iid should point to. (
instance_references) - Fields that contain an iid, which should point to the node that belongs to it. (
unresolved_references)
EntityRef fields are unresolved when they are encountered by the importer, because the node it points to might not exist yet (e.g. an entity from Level_1 may point to an entity in Level_2).
To solve this, this LDTK importer provides utility functions for you to add/update these references, which the importer will then try to resolve them after all the post-import scripts have run, before saving the scene.
These functions are:
update_instance_reference(iid, scene)add_unresolved_reference(scene, property_name)
Check out the following Entity Post-Import script to see how they are used:
@tool
## Entity Post Import Example, showcasing how to handle EntityRefs.
const Util = preload("res://addons/ldtk-importer/src/util/util.gd")
const SceneTest = preload("res://node_test.tscn")
func post_import(entity_layer: LDTKEntityLayer) -> LDTKEntityLayer:
var entities: Array = entity_layer.entities
for entity in entities:
# Create entity node (simple example)
var scene = SceneTest.instantiate()
entity_layer.add_child(scene)
# Update 'iid' to reference this entity node
Util.update_instance_reference(entity.iid, scene)
# Add unresolved reference (e.g. EntityRef field)
if "Entity_ref" in entity.fields:
var ref = entity.fields.Entity_ref
if ref != null:
scene.ref = ref
Util.add_unresolved_reference(scene, "ref")
return entity_layer
Here is the example SceneTest scene:
@tool
extends Node2D
@export var ref: NodePath # The EntityRef we are updating via post-import
The entity scene holding an EntityRef variable must have the
@toolannotation in its attached script, otherwise variables cannot be updated this way in the Editor.
If you run into any problems, please file an issue!
🫂 Special Thanks
- amano-ldtk for original inspiration
- Cammin for helpful feedback!