This guide explains how targeting works in Grid Placement 6.0.0.
Version note: This guide is for the 2D
TileMapLayerplacement path in Grid Placement 6.0.0.
Main Pieces
| Piece | What it does |
|---|---|
GridPositioner2D |
Tracks the cursor/controller target cell and snaps to the grid. |
TargetingShapeCast2D |
Detects targetable objects for move/demolish/highlight workflows. |
GridTargetingState |
Stores the active target map, positioner, target object, and targeting flags. |
TargetHighlighter |
Optional visual feedback for the currently targeted object. |
GridPlacementHost |
Reads the active session/targeting state while dispatching placement input. |
GridPositioner2D
GridPositioner2D handles the visible grid cursor/target position.
It is responsible for:
- Mouse follow: tracking the cursor and snapping to tile centers.
- Keyboard/controller movement when configured.
- Recenter behavior when entering placement modes.
- Visibility logic based on mode, settings, and UI/input state.
It does not own shapecast collision detection or rotation/flip behavior.
TargetingShapeCast2D
TargetingShapeCast2D is the collision-query layer. Its job is to update GridTargetingState.target from the current physics collision result.
- If
GridTargetingState.is_manual_targeting_activeis true, automatic target updates are skipped. - When a collider is found, the shape cast resolves the targetable root when possible.
- When no collider is found, the current target is cleared.
Use this for object targeting, not for deciding whether a new object placement is valid. Placement validity belongs to placement rules.
GridTargetingState
The targeting state is the shared resource other systems consume.
Common fields:
var target:Node2D
var target_map:TileMapLayer
var maps:Array[TileMapLayer]
var positioner:Node2D
var is_manual_targeting_active:boolPlacementLevelContext normally assigns target_map, and GridPositioner2D registers itself as the positioner.
Processing Flow
User input
→ GridPositioner2D moves to snapped tile center
→ TargetingShapeCast2D queries physics collisions at that center
→ GridTargetingState.target updates with the found object, if any
→ placement, manipulation, or UI reads the targeting stateEssential Setup for Plugin Users
If targeting looks broken, check these first:
PlacementLevelContext.target_mapis assigned.GridPositioner2Dwas injected or registered successfully.TargetingShapeCast2Dwas injected or registered successfully.- Your shapecast collision mask matches the targetable layers.
- The mode/settings allow the positioner to stay active/visible.
- Your UI is not consuming the input path you expect.
Collision Layer vs Collision Mask for Targeting
TargetingShapeCast2D uses Godot's collision system to detect objects.
| Property | What it means | Used by ShapeCast2D to... |
|---|---|---|
collision_mask on TargetingShapeCast2D |
Which layers to check | Find objects. |
collision_layer on target objects |
Which layers the object is on | Be detectable by matching masks. |
Detection works only when the shapecast mask overlaps the target object's layer.
TargetingShapeCast2D:
collision_mask: includes layer 10
Placed object:
collision_layer: includes layer 10Common mistake: setting only collision_mask = 10 on placed objects. That lets the object detect layer 10 things, but it does not put the object on layer 10. The shapecast cannot find it unless the object's collision_layer includes the target layer.
Avoid Duplicate Targeting Layers
Only the intended target/root should own the targeting layer.
# Good: one clear target owner
GeyserPumpRoot:
collision_layer: includes target layer
StaticBody2D:
collision_layer: does not include target layer
# Risky: multiple target owners
GeyserPumpRoot:
collision_layer: includes target layer
StaticBody2D:
collision_layer: also includes target layerWhen multiple nodes in one scene have the targeting layer, the shapecast may report a child collider instead of the root you intended.
ShapeCast Collision Flags
Godot ShapeCast2D collision flags matter.
TargetingShapeCast2D:
collide_with_areas: true
collide_with_bodies: trueUse collide_with_areas = true when your target objects are Area2D. Use collide_with_bodies = true when your target objects are StaticBody2D or other physics bodies. Many placed objects use bodies, so leaving collide_with_bodies false is a common cause of move/demolish/highlight failing.
Quick diagnostic:
print("TargetingShapeCast2D: areas=%s, bodies=%s" % [
$TargetingShapeCast2D.collide_with_areas,
$TargetingShapeCast2D.collide_with_bodies
])TargetingShapeCast2D.debug_log_collisions can also be enabled for verbose collision logging when a logger is available.
Preview Stability and Manual Targeting
During active building/manipulation flows:
TargetingShapeCast2Dcan stop auto-updating when manual targeting is active.- Collision exclusions can prevent previews from blocking their own placement validation.
- Manipulation visuals are handled by
ManipulationParent, not the positioner.
Game-Owned World Facts
The normal placement path decides a target cell and runs placement rules from Godot collision and your configured rules. Some projects also have additional blocked-cell information that the plugin's normal collision checks do not represent — for example, an occupancy grid, a reserved build zone, or terrain data your game tracks separately.
Use PlacementWorldFactsProvider2D for that case. The positioner still decides the current target cell, but the provider answers whether your game considers that cell blocked. The matching rule, ProviderCellBlockRule2D, turns that answer into normal placement validation issues. See Placement World Facts Provider for examples and advanced sources.
Beginner rule of thumb:
GridPositioner2D = where the cursor is
PlacementWorldFactsProvider2D = what your game knows about that cell
ProviderCellBlockRule2D = how that knowledge blocks placementSee Placement World Facts Provider for examples.
Common Targeting Problems
- Positioner never appears
- Check mode/state injection.
- Check targeting settings visibility rules.
- Target object never updates / move-demolish-highlight does not work
- Check
collide_with_areasandcollide_with_bodiesfirst. - Check
TargetingShapeCast2D.collision_maskmatches your targeting layer. - Check that the target object has
collision_layerincluding that same layer. - Enable
TargetingShapeCast2D.debug_log_collisionsfor diagnostics.
- Check
- Cursor does not move
- Check
GridPositioner2Dinput settings and target map wiring.
- Check
- Move/build targeting acts frozen
- Check whether manual targeting is intentionally active.