Quick answer: Convert finalized CSG sub-trees to ArrayMesh: select the root CSG, Mesh menu → Convert → ArrayMesh. Disable Use Collision while sketching. Limit each CSG tree to ~20 child operations; split larger structures into separate trees.

CSG is great for blocking out levels until it isn’t. Add the 25th cylinder window to a wall and the editor stops responding for 5 seconds on every move. Conversion to ArrayMesh is the long-term answer; structuring CSG into smaller trees is the short-term one.

The Symptom

Editor stalls or freezes for seconds after each CSG edit. Saving the scene takes long. Closing the scene cleans up but reopening is slow.

What Causes This

CSG (Constructive Solid Geometry) operates by performing boolean operations between meshes. Every property change — transform, parameter, child add/remove — triggers a full rebuild of the affected subtree. Cost grows with the number of operations and the polygon count of each.

The Fix

Step 1: Convert finalized regions. Once a CSG sub-region is final (you’re not iterating on it):

  1. Select the root CSGCombiner or CSG primitive.
  2. 3D viewport menu (top of viewport) → Mesh → Convert → ArrayMesh.
  3. The node becomes a MeshInstance3D with the baked geometry. The CSG tree is gone.

Editor performance returns to normal for that region. You lose the ability to non-destructively edit the boolean operations — that’s the trade-off.

Step 2: Disable Use Collision while sketching. CSG nodes have Use Collision = true by default, which adds a collision generation step on top of the visual rebuild. Turn off while you’re iterating; turn on at conversion time.

Step 3: Split into small trees. A “wall with windows” can be one CSGCombiner3D. The whole building should be many CSGCombiners (one per wall, one per ceiling), each with maybe 20 children. Editing one tree only rebuilds that tree.

Runtime CSG

If your game uses runtime CSG (destructible terrain, procedural geometry), you can’t pre-convert. Limit live CSG trees to small areas and rely on caching. set_use_collision(true) only after the geometry is final — constant collision regeneration is expensive.

The Right Tool for Final Levels

For shipped game levels, do the rough block-out in CSG, then export the geometry to Blender (use the addon or just convert and export glTF), refine, re-import as a regular MeshInstance3D. Your finished level isn’t paying CSG rebuild cost ever again.

Verifying

Open the .tscn file. Count CSG-prefixed nodes. If it’s in the hundreds, conversion to ArrayMesh would speed every operation in the editor. After conversion, the equivalent ArrayMesh nodes are simple MeshInstance3D with embedded data — faster to load, faster to edit.

“Convert when done. Smaller trees while iterating. CSG for sketches, ArrayMesh for ship.”

Related Issues

For Godot CSG to static, see CSG mesh collision. For editor performance, see editor slow scenes.

Convert. Split. The editor breathes.