Object placement in 2D/3D follows the same core loop:
select
→ target
→ preview
→ validate
→ confirm
→ validate again
→ commit
→ record placement/occupancyThe preview is never authority. Final validation at commit time decides whether the world changes.
Object placement
1. Select
The active PlacementSession selects a ScenePlacementEntry. Profiles/categories on the entry define supported tools and reusable rules.
2. Target
Targeting depends on coordinate mode/dimension:
- 2D GRID →
TileMapLayercell. - 3D GRID →
GridMapcell/EDGE/FACE mount. - SMOOTH → world-space position/footprint.
3. Preview and validate
Preview shows the transform plus current valid/blocked feedback. Validation may include:
- bounds/surface/support;
- occupancy and mounts/sockets;
- collision/environment checks;
- profile/custom rules;
- game-owned world facts/cost restrictions.
UI should display the placement result rather than reimplementing the rules.
4. Commit
Confirm runs final validation again. On success the plugin:
- creates/commits the object;
- updates placement identity and occupancy/mount state;
- emits the supported lifecycle/result information;
- keeps persistence/manipulation state consistent.
On failure, authoritative world state remains unchanged.
Object LINE placement
Object LINE is opt-in by profile/category.
start line
→ drag to end
→ preview generated placements
→ confirm/release
→ validate generated placements
→ commit according to the supported line policyUse it for repeatable objects such as posts/fence-like props when each result should still be an individual scene object.
2D terrain painting
Terrain painting applies only to TileMapLayer in the 6.0 public contract.
| Brush | Interaction |
|---|---|
SINGLE |
Preview one cell → confirm. |
LINE |
Drag start→end → commit generated line. |
RECTANGLE_FILL |
Drag corners → commit filled region. |
RECTANGLE_OUTLINE |
Drag corners → commit perimeter. |
FLOOD_FILL |
Anchor/preview region → second confirm commits. |
The real TileMapLayer must not mutate during preview.
Large generated brushes are bounded by PlacementSettings.max_terrain_brush_cells; see Surface & Brush Reference.
Cancel and selection changes
Cancel/change-mode/change-selection should clear transient preview/pending state without changing committed placement/terrain.
This also applies when a session/controller is unregistered or the owning scene exits.
Manipulation
Move/rotate/flip/demolish use the plugin manipulation path rather than direct node mutation from UI code.
That matters because supported manipulation must keep these in sync:
- transform;
- occupancy/mount/socket state;
- validation;
- stable placement identity;
- persistence data;
- optional refund behavior.
See Manipulation: Service vs Parent.
Side effects
Perform game-side effects only at the correct lifecycle stage.
Examples:
- inventory/cost changes after a successful placement decision;
- configure a new instance through the supported pre-add hook;
- update quests/progression from successful placement/removal results;
- issue refunds only after demolition succeeds.
Do not spend resources or save progression because a preview is currently valid.
3D support-specific workflow
GRID structure placement adds mount/support decisions to the same loop:
target CELL/EDGE/FACE
→ resolve support/slope
→ preview + indicators
→ final validation
→ commit canonical mount/occupancy recordSMOOTH adds world-footprint occupancy and optional world sockets instead.
See 3D Object Placement and Grid vs Smooth Placement.
Common failures
- missing/incorrect level context;
- UI consumes placement input;
- targeting collision mask cannot see the intended surface/object;
- object collision/occupancy already blocks the target;
- GRID mount/provider is incompatible or occupied;
- slope/support policy rejects the 3D footprint;
- SMOOTH footprint is missing;
- custom game rule/world fact rejects the action.
Read the returned failure/report first. Fix the owning configuration/rule rather than bypassing validation.