# 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