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
This commit is contained in:
@@ -0,0 +1,245 @@
|
||||
# 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 | 1–2 |
|
||||
|
||||
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 | 4–8 (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 | 3–4 wide | Comfortable movement |
|
||||
| Bombsite | 8×8 minimum | Playable site area |
|
||||
| Spawn room | 6×8 | 5 players need space |
|
||||
| Mid area | 6–8 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
|
||||
Reference in New Issue
Block a user