Use this guide when the plugin loads but placement, preview, terrain painting, or manipulation does not behave as expected.
Version note: This guide is for Grid Placement 6.0.0. The supported buyer-facing path is 2D placement on
TileMapLayerin Godot 4.5.0 through 4.7.
Start Here
Before changing code, check the Godot Output panel. Grid Placement reports missing context and setup problems there.
Then confirm the basic setup:
- Plugin enabled - Project Settings -> Plugins -> Grid Placement is enabled.
- Input actions installed - run Project -> Tools -> Grid Placement / Setup Default Input Actions.
- Host configured -
GridPlacementHosthas a validPlacementSession. - Level context assigned -
PlacementLevelContext.target_mapandobjects_parentare set. - Owner assigned -
PlacementOwner.owner_rootis set. - Positioner active -
GridPositioner2Dis inside the active scene/session scope. - UI not blocking input - full-screen HUD
Controlnodes use Mouse Filter: Ignore or Pass unless they are meant to consume clicks.
Related setup guide: Getting Started
Preview Does Not Appear
Check:
- A
ScenePlacementEntryis selected. - The entry's
packed_scenepoints to a validPackedScene. PlacementLevelContext.target_mapis assigned.GridPositioner2Dis updating the target cell.- The plugin input actions exist in Project Settings.
- UI controls are not consuming the click or selection event.
Beginner note: the preview is temporary. It should move with targeting and should not be saved as a real placed object.
Object Will Not Place
If the preview appears but confirm does not place an object, check:
PlacementLevelContext.objects_parentis assigned.- The selected
ScenePlacementEntry.packed_sceneis valid. - Placement rules are passing.
- Collision layers match the rules you enabled.
- The object is not outside the target map bounds.
- Any material/cost rule can actually spend from your inventory bridge.
A failed placement should produce a PlacementReport/action result with issues. Surface that message in your UI instead of guessing.
TargetingShapeCast2D Does Not Detect Placed Objects
This usually means collision layer or mask wiring is wrong.
1. Collision flags
If your target objects use Area2D, the shapecast must collide with areas. If they use StaticBody2D, it must collide with bodies.
TargetingShapeCast2D:
collide_with_areas: true # needed for Area2D targets
collide_with_bodies: true # needed for StaticBody2D targets
2. Collision layer vs collision mask
A collision layer says what the object is. A collision mask says what the detector looks for.
Your placed object must be on a layer that TargetingShapeCast2D.collision_mask can see.
PlacedObjectRoot or physics body:
collision_layer: includes the targeting layer
TargetingShapeCast2D:
collision_mask: includes that same layer
Having only collision_mask on the placed object is not enough. The shapecast cannot detect an object unless the object is on a matching collision layer.
3. Avoid duplicate targeting layers in one object
If both the root and a child physics body use the targeting layer, the shapecast may report the wrong node.
Prefer one clear target owner for manipulation/demolish.
See Targeting Flow for more detail.
UI Blocks Placement Clicks
Godot Control nodes can consume mouse input before _unhandled_input reaches the placement host.
Fix:
- Set non-interactive HUD containers to Mouse Filter: Ignore or Pass.
- Keep buttons interactive only where clicks should operate the UI.
- Test placement with the HUD hidden. If placement works with HUD hidden, the UI is consuming input.
Terrain Preview Does Not Show
Check:
- A
TerrainPreviewnode exists under the same injected scene scope as the host and target map. - A terrain entry/palette is selected.
PlacementLevelContext.target_mappoints to the realTileMapLayer.- The selected terrain can be resolved against the target map's
TileSet.
Do not manually add TerrainPreviewLayer, TerrainInvalidPreviewLayer, or preview groups. TerrainPreview creates and manages its runtime preview layers.
Terrain Paints the Wrong Cells
Check:
- The
GridPositioner2Dtransform matches the target map and tile size. - The target map is the intended
TileMapLayer. - You are not mixing local/global coordinates in custom code.
- Brush shape selection matches the expected input flow.
Input flow reminder:
- SINGLE: one click/confirm paints one cell.
- LINE / RECTANGLE_FILL / RECTANGLE_OUTLINE: press, drag, release.
- FLOOD_FILL: first click anchors the preview, second click commits.
If a large line/rectangle/flood-fill commits fewer cells than expected, check PlacementSettings.max_terrain_brush_cells (default 4096, hard ceiling 16384). See 6.0 Surface and Brush Reference.
Move, Rotate, Flip, or Demolish Does Nothing
Check:
- The placed object has a
Manipulatablecomponent. ManipulatableSettingsallows the operation you are trying to use.- The object can be detected by
TargetingShapeCast2D. - The targeting collision layer is on the intended object/root.
- The active session has manipulation services enabled through its settings/service group.
If move says the object is not movable, inspect the object's ManipulatableSettings first.
Save Data Contains Preview Objects
Preview and manipulation copies are temporary. Your save system should persist only real placed objects.
Practical checks:
- Do not save nodes marked as preview/manipulation helpers.
- Prefer a clear group or metadata marker for real placed objects in your own game.
- Query under
PlacementLevelContext.objects_parentonly after placement has succeeded.
Web Export: Resources or Rules Do Not Load
Web export is stricter about resources than desktop runs.
Check:
- Rules and settings are saved as external
.tresfiles when possible. - Avoid relying on embedded
SubResource(...)entries for important placement rules. - Save nested resource defaults explicitly when a rule depends on them.
- Test a web export before release, not only the editor run.
See Web Export Guide for details.
How to Debug Without Guessing
- Reproduce the issue in the smallest scene possible.
- Check the Output panel for setup warnings.
- Call
host.is_ready()after setup. - Call
host.get_runtime_issues()when available in your scene path. - Verify
PlacementLevelContext.target_mapandobjects_parentin the inspector. - Verify
PlacementOwner.owner_root. - Temporarily hide the UI and test whether input reaches placement.
- Test with a simple one-cell object before testing line/flood-fill workflows.
Related Guides
- Getting Started
- Architecture Overview
- Targeting Flow
- Placement Workflow
- 6.0 Surface and Brush Reference
- Manipulation: Service vs Parent
- Refund on Demolish
- Web Export Guide
Source
docs/v6-0/guides/troubleshooting.md
Plugin docs root:gdscript/plugins/grid_placement_dev/docs