Files
tactical-shooter/docs/mapmaking/02-building-geometry.md
T
shawn 34507f9043 docs: community mapmaking documentation (7-file SDK guide)
- docs/mapmaking/00-index.md — SDK overview with workflow diagram
- docs/mapmaking/01-getting-started.md — template setup & first map
- docs/mapmaking/02-building-geometry.md — CSG guide & prefab reference
- docs/mapmaking/03-lighting-and-env.md — LightmapGI baking guide
- docs/mapmaking/04-validation.md — validator CLI & CI/CD usage
- docs/mapmaking/05-packaging-and-shipping.md — .pck pipeline
- docs/mapmaking/06-faq-and-troubleshooting.md — 30+ common issues
- README.md — add mapmaking SDK link to features list
2026-07-01 18:47:06 -04:00

246 lines
7.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Building Geometry with CSG
Tactical Shooter maps are built with Godot's **CSG** (Constructive Solid
Geometry) system — the same tool you'd use in a 3D modeller, but inside the
Godot editor. CSG nodes let you cut, join, and extrude geometry in real-time
with instant visual feedback.
## CSG Basics
### CSG Node Types
| Node | Use | Shape |
|------|-----|-------|
| `CSGBox3D` | Walls, floors, ceilings, pillars | Rectangular prism |
| `CSGSphere3D` | Domes, curved edges | Sphere |
| `CSGCylinder3D` | Columns, pipes | Cylinder |
| `CSGCombiner3D` | Group container, non-collidable parent | — |
| `CSGPolygon3D` | Extruded 2D path | Custom shape |
### CSG Operations
Each CSG node has an **Operation** property that determines how it combines
with sibling CSG nodes in the same parent:
| Value | Operation | Effect |
|-------|-----------|--------|
| 0 | **Union** | Adds to existing geometry (default) |
| 1 | **Subtraction** | Cuts a hole through parent |
| 2 | **Intersection** | Keeps only overlapping volume |
**Example — a window cutout:**
```
Wall (CSGBox3D, Union)
└── WindowCutout (CSGBox3D, Subtraction)
```
This subtracts the window shape from the wall. Move/resize the subtraction
child to reposition the window.
### Key Properties
- **`use_collision`** (bool) — Must be `true` on all floor/wall/ceiling CSG
nodes so players and bullets collide with them
- **`use_shadows`** (bool) — Enable shadow-casting on geometry
- **`material`** — Assign placeholder materials during construction; final
materials come from the main game project library
- **`snap_mode`** — Controls vertex snapping (useful for aligning geometry)
## Building a Room
A basic room needs 3 CSG layers:
```
Room (CSGCombiner3D)
├── Floor (CSGBox3D, Union, use_collision=true)
├── Walls (CSGCombiner3D)
│ ├── Wall_North (CSGBox3D, Union)
│ ├── Wall_South (CSGBox3D, Union)
│ ├── Wall_East (CSGBox3D, Union)
│ └── Wall_West (CSGBox3D, Union)
└── Ceiling (CSGBox3D, Union, use_collision=true)
```
### CSG Building Tips
1. **Overlap slightly** — Walls should extend past the floor edge by ~0.1 units
to prevent light leaks (thin gaps let light bleed through)
2. **Keep CSG simple** — Use as few CSG nodes as possible. A wall panel is one
CSGBox3D, not 4 extruded edges
3. **Convert to Mesh when done** — Once geometry is final, select all CSG
nodes → right-click → **Convert CSG to Mesh**. This bakes them into static
MeshInstance3D nodes that perform much better
4. **Avoid curved CSG for floor/walls** — CSGSphere3D and CSGCylinder3D are
expensive. Use them sparingly
## Prefab Reference
The template provides 6 drag-and-drop prefab nodes. Each is an `assets/prefabs/*.tscn`
file that you instantiate into your scene.
### ct_spawn.tscn
| Property | Value |
|----------|-------|
| Type | `Marker3D` (green pad + arrow) |
| Group | `ct_spawn` |
| Purpose | CT team spawn position |
| Quantity | 5 (one per player) |
The +Z arrow (blue axis) shows the direction players face when they spawn.
Position the pad at floor level — make it flush with the floor surface.
**Customisation:** Duplicate instances rather than editing the prefab. Adjust
only position and rotation. The green pad is cosmetic.
### t_spawn.tscn
| Property | Value |
|----------|-------|
| Type | `Marker3D` (red pad + arrow) |
| Group | `t_spawn` |
| Purpose | Terrorist team spawn position |
| Quantity | 5 |
Same usage as `ct_spawn` but red. Place at the opposite end of the map.
### buy_zone.tscn
| Property | Value |
|----------|-------|
| Type | `Area3D` with `CollisionShape3D` |
| Group | `buy_zone` |
| Purpose | Purchase-eligible zone |
| Quantity | 12 |
The game monitors `body_entered` / `body_exited` on these areas to show/hide
the buy menu. Resize the child CollisionShape3D to match the room shape.
**Additional groups (optional):**
- `ct_buy` — Only CT team can buy in this zone
- `t_buy` — Only T team can buy in this zone
If omitted, any player inside a `buy_zone` can buy (suitable for shared mid areas).
### bomb_site.tscn
| Property | Value |
|----------|-------|
| Type | `Area3D` with `CollisionShape3D` |
| Group | `bomb_site` |
| Purpose | Bomb plant zone |
| Quantity | 2 (A and B) |
Rename instances to `BombsiteA` and `BombsiteB`. Resize the CollisionShape3D
to cover the plantable area. Visual: semi-transparent orange floor panel.
**Additional groups (strongly recommended):**
- `bombsite_a` — Identifies this as site A
- `bombsite_b` — Identifies this as site B
### cubemap_origin.tscn
| Property | Value |
|----------|-------|
| Type | `Node3D` (blue sphere marker) |
| Group | `cubemap_origin` |
| Purpose | Marks ReflectionProbe capture position |
| Quantity | 1 |
Place at eye height ≈ 1.6 units above the floor in the most visually prominent
area (usually mid-map or the central choke point). The ReflectionProbe is a
separate node that should be placed at this marker's position after geometry
is finalised.
### map_bounds.tscn
| Property | Value |
|----------|-------|
| Type | `Area3D` with `CollisionShape3D` |
| Group | `map_bounds` |
| Purpose | Out-of-bounds kill wall |
| Quantity | 48 (enclose the perimeter) |
**Usage:**
- Place one instance per perimeter face (north, south, east, west)
- Resize each CollisionShape3D to form a closed box around the playable area
- Make the floor-bound wall tall enough that players can't jump over it
- The game detects `body_exited` from these areas and teleports/kills
out-of-bounds players
> **Performance tip:** `map_bounds` nodes should be as thin as practical —
> these are just detection triggers, not visual geometry. A thickness of 0.5
> units is sufficient.
## Advanced Geometry Techniques
### Corridors and Hallways
Build a corridor as a CSGCombiner3D with union floor + walls + ceiling and
subtraction nodes for doors/windows:
```
Corridor (CSGCombiner3D)
├── Floor (CSGBox3D, Union)
├── LeftWall (CSGBox3D, Union)
│ └── Door1 (CSGBox3D, Subtraction)
├── RightWall (CSGBox3D, Union)
│ └── Window1 (CSGBox3D, Subtraction)
└── Ceiling (CSGBox3D, Union)
```
### Ramps and Stairs
Use multiple CSGBox3D nodes at increasing heights. Stack them like steps and
wrap in a CSGCombiner3D for a clean hierarchy:
```
Stairs (CSGCombiner3D)
├── Step1 (CSGBox3D, Union, pos=(0, 0, 0))
├── Step2 (CSGBox3D, Union, pos=(0, 0.5, 1))
├── Step3 (CSGBox3D, Union, pos=(0, 1.0, 2))
└── Step4 (CSGBox3D, Union, pos=(0, 1.5, 3))
```
For ramps, rotate a CSGBox3D or use CSGPolygon3D with an extruded triangle shape.
### Map Scale Reference
| Element | Size (units) | Notes |
|---------|-------------|-------|
| Player height | 1.8 | Eye level ≈ 1.6 |
| Player width | 0.5 | Collision capsule radius |
| Doorway | 1.5 × 2.5 | Wide enough for 2 players |
| Corridor | 34 wide | Comfortable movement |
| Bombsite | 8×8 minimum | Playable site area |
| Spawn room | 6×8 | 5 players need space |
| Mid area | 68 wide | Main chokepoint |
## From CSG to MeshInstance3D (Baking)
When your geometry is **final** (no more changes expected):
1. Select all CSG nodes in the scene tree
2. Right-click → **Convert CSG to Mesh**
3. This replaces CSG nodes with static `MeshInstance3D` nodes
4. The mesh instances are much more performant
**Don't convert until you're done** — CSG is editable, MeshInstance3D is not.
Keep working in CSG mode; convert only for final optimisation before packaging.
## Performance Budget
See the [Validator guide](04-validation.md) for detailed numbers, but the key
geometry rules are:
- **≤ 50,000 triangles** total across all meshes
- **≤ 5,000 triangles** per individual mesh (recommended; enforced as warning)
- Use CSG for blockout only — convert to mesh before shipping
- Avoid CSGSphere3D in visible areas; use hand-modelled meshes
## Next Steps
- [Lighting & Environment Setup](03-lighting-and-env.md) — light your map
- [Map Validation](04-validation.md) — run the validator on your scene