Grid Placement validates placement in two layers:
- Core placement validation — dimensional correctness owned by the plugin, such as occupancy, GRID mounts, SMOOTH footprints, and 3D support/slope checks.
- Game-authored rules — optional project policy such as costs, unlocks, protected zones, or game-owned world facts.
Do not re-create core 3D CELL/EDGE/FACE/slope validation in a custom 2D tile rule.
Core validation by workflow
| Workflow | Core checks include |
|---|---|
| 2D object placement | target/bounds, footprint/indicator checks, occupancy/collision, configured rules |
| 2D terrain painting | terrain target/brush validation, paint gates/hooks |
| 3D GRID | footprint occupancy, CELL/EDGE/FACE mount validity, snap/provider rules, ground/support/slope policy |
| SMOOTH | world footprint occupancy, optional environment/physics checks, optional sockets |
The UI should consume the current placement result/report rather than duplicate any of these checks.
Game-authored rule classes
For the current 2D rule pipeline:
| Base class | Use when |
|---|---|
PlacementRule |
The rule checks game/session state and does not need per-cell indicator positions. |
TileCheckRule |
The rule needs 2D covered cells/indicator-specific feedback. |
RuleResult |
Carries pass/fail issues from rule validation. |
TileCheckRule is a 2D tile/indicator concept. It is not the extension point for 3D mount or slope algorithms.
See Custom Placement Rules for authoring examples.
Where rules are configured
| Location | Scope |
|---|---|
PlacementSettings.placement_rules |
Shared/default rules. |
PlacementProfile.placement_rules |
Rules shared by a category/profile. |
ScenePlacementEntry.placement_rules |
Rules unique to one placeable. |
Start with the narrowest scope that matches the requirement. Promote a rule to a profile/global setting only when several entries genuinely share it.
Base-rule overrides
Profiles/entries can opt out of inherited base rules where the public configuration allows it. Use that deliberately.
Good reason: a decoration category intentionally has different overlap policy.
Bad reason: bypassing a failing core placement check instead of fixing the configuration/collision/support problem.
Costs and inventory
For new id-keyed integrations, SpendMaterialsRuleById is the preferred cost rule. It validates availability and performs the spend through the configured game/inventory bridge at the successful lifecycle stage.
Do not subtract the same materials again from UI/success handlers.
SpendMaterialsRuleGeneric exists for legacy ResourceStack-based integrations; new projects should prefer the id-keyed path.
World facts
When placement must respect facts owned by your game rather than plugin collision/occupancy, expose those facts through the appropriate provider/bridge instead of importing game classes into plugin rules.
The shipped PlacementWorldFactsProvider2D / ProviderCellBlockRule2D path is specifically for 2D cell facts such as reserved or externally occupied cells.
See Placement World Facts Provider.
Collision and indicators
For 2D tile/indicator rules, collision shapes can define the covered footprint used by tile checks. Make sure collision layers/masks match what the rule/targeting path is expected to see.
Simple mental model:
- layer = what an object is on;
- mask = which layers a query checks.
If a 2D collision rule does not see an object, inspect the layer/mask setup before weakening the rule.
Validation must be side-effect free
Preview validation can run repeatedly. Do not spend inventory, save progression, spawn permanent objects, or trigger irreversible game state from validation.
Perform irreversible effects only after the placement action succeeds through the supported lifecycle/apply/result path.
Placement vs manipulation vs terrain
These workflows do not all use identical rule sources:
- New object placement uses placement/profile/entry rules plus core dimensional validation.
- Manipulation revalidates the moved/rotated object's supported placement state through the manipulation path.
- 2D terrain uses terrain validation/paint gates/hooks rather than pretending terrain cells are scene-object rules.
Keep policy in the workflow that owns the state being changed.
UI rule
UI displays placement outcomes. It should not become a second validator.
Good:
- show report issues;
- show locked/unavailable entries from session state;
- refresh inventory after successful placement.
Avoid:
- re-running collision/support logic in UI;
- spending resources in both rules and UI;
- turning a green preview into an assumption that commit already succeeded.