This was the longest day of the project so far. Over 30 commits spanning from midnight to evening. The goal: go from “rooms exist as volumes” to “rooms you can actually walk through.”

Doorway cutting

First up: DoorwayCutter. When two rooms share a wall, we need to carve a doorway so the player can pass through. This uses CSG SubtractAsync — subtract a door-shaped block from the wall slab. The first implementation worked in isolation but failed when integrated, because CSG operations require both parts to be descendants of Workspace. Our wall slabs were parented to a Model. Quick fix: temporarily reparent to Workspace, perform the operation, reparent back.

The CSG shell experiment (and why we killed it)

Then we tried something ambitious: building room walls as CSG shells instead of individual slabs. Take a solid block, subtract a slightly smaller block from the inside, and you get a hollow room in one operation. Elegant — one union instead of six slabs.

In practice, it fell apart:

  • Physics collision shapes diverged from the visual mesh. Players would walk through visible walls or collide with invisible ones.
  • Performance was worse. Six slabs are six simple collision checks. One CSG union is a complex mesh decomposition.
  • Cutting doorways into an already-unioned shell frequently failed or produced corrupted geometry.

We spent four commits trying to make it work (separating visual and collision geometry, different parenting strategies, simplified shell shapes). Then we reverted to slab-based walls. Six Parts per room. Simple, predictable, and fast. The CSG experiment taught us where the boundaries of Roblox’s CSG system are — useful knowledge, but not the path forward for runtime-generated geometry.

VolumeGraph: The second generator

PathGraph from yesterday still produced overlap issues in complex layouts. The root cause was fundamental: placing rooms along a path and checking for collisions after placement is fragile. The check can pass for position A but Room A’s footprint creates an overlap with something placed later.

VolumeGraph flips the approach: volume-first.

  1. Define a 3D grid of possible room positions
  2. Place the starting room in a grid cell
  3. Grow by filling adjacent grid cells
  4. Overlap is impossible because each cell is exclusive

This required its own round of bug fixes — rooms positioned by outer shell vs. inner volume (an off-by-wall-thickness error), growth strategies that accidentally produced disconnected layouts — but the foundation is more solid. The grid guarantees no overlap at the structural level, not as a runtime check.

Ladders

Multi-level dungeons need vertical movement. When a doorway connects rooms at different heights, we generate ladders. Getting the placement right took four commits: centering them under the door opening, offsetting into the room (not embedded in the wall), raising the height threshold (small drops don’t need ladders), and placing ladders on both sides of elevated doorways.

The dungeon lives

By end of day, we had a sequential dungeon generation system that produces multi-room, multi-level layouts with doorways, ladders, wall trusses for decoration, and a spawn point. You can walk through it. The spawn point placement was still broken (final commit is a safety net that teleports the player if they spawn outside the rooms), but the dungeon itself is real.

30+ commits. One working dungeon. It was worth every hour.