Godot入門:CSGBox3Dの使い方と活用法

はじめに

3Dレベルデザインやプロトタイプ開発で、複雑な形状を素早く作る必要があることがあります。「この部分を切り取りたい」「2つの形を組み合わせたい」——こうした要望を簡単に実現するのがCSGBox3Dです。CSG(Constructive Solid Geometry)という手法でメッシュを組み合わせることで、複雑な3D形状を効率的に設計できます。

本記事では、CSGBox3Dとその仲間たち、そしてCSGの本質を、実装パターンを交えて解説します。

CSGBox3Dとは?

CSGBox3Dは、ブーリアン演算を用いて立方体型の3Dオブジェクトを作成・結合するノードです。他のCSGプリミティブと組み合わせることで、複雑な形状を簡単に設計できます。

継承ツリー:

CSGBox3D → CSGPrimitive3D → CSGShape3D → GeometryInstance3D → VisualInstance3D → Node3D → Node → Object

CSGの「構築的立体幾何」とは、単純な形(立方体、球体、円柱)を組み合わせ、加算・減算・交差といった演算を用いて複雑な形を作る手法です。ゲーム開発では、プロトタイプやレベルデザインの高速化に欠かせません。

このノードを使うべき場面

活躍する場面:

  • ゲームプロトタイプの素早い環境構築
  • レベルデザインの初期段階(調整が多い場合)
  • 建築物やダンジョンの型抜き(ドア・窓の形状)
  • 複雑な壁配置や障害物の配置
  • ゲームジャムなど時間が限定された開発

使わない場面:

  • 本番ゲーム(パフォーマンス最適化後は MeshInstance3D に置き換え)
  • 高度にディテールが必要なアセット(モデリングソフトで作成)
  • 頻繁に動く複雑な形状(負荷が高い)

主なプロパティと機能

CSGBox3Dの基本的なプロパティを表にまとめました:

プロパティ説明デフォルト値
sizeVector3立方体のサイズ(X, Y, Z)Vector3(2, 2, 2)
materialMaterial表面のマテリアルnull
use_collisionbool衝突判定を有効にするかfalse
collision_layerint所属するコリジョンレイヤー1
collision_maskint検出するコリジョンレイヤー1
operationenumブーリアン演算の種類OPERATION_UNION

基本的な使用例:


extends Node3D

@onready var csg_box = $CSGBox3D

func _ready():
	# シンプルな立方体
	csg_box.size = Vector3(2, 2, 2)
	csg_box.material = StandardMaterial3D.new()
	csg_box.material.albedo_color = Color.GRAY

	# 衝突判定を有効化
	csg_box.use_collision = true
	csg_box.collision_layer = 1
	csg_box.collision_mask = 1

	print("CSGBox3D が作成されました: サイズ", csg_box.size)
CSGのブーリアン演算(UNION, INTERSECTION, SUBTRACTION)
CSGのブーリアン演算により、複雑な形状を簡単に作成できます

ドア・窓の型抜き実装例:


extends Node3D

func _ready():
	# 壁となるCSGBox3D(親)
	var wall = CSGBox3D.new()
	wall.size = Vector3(10, 5, 1)
	wall.material = StandardMaterial3D.new()
	wall.material.albedo_color = Color(0.8, 0.7, 0.6)  # 土色
	wall.use_collision = true
	add_child(wall)

	# ドアの穴をくり抜く(CSGBox3D)
	var door_hole = CSGBox3D.new()
	door_hole.size = Vector3(2, 3, 1.5)
	door_hole.position = Vector3(3, 1, 0)  # 壁の右上に配置
	door_hole.operation = CSGShape3D.OPERATION_SUBTRACTION  # 減算演算
	wall.add_child(door_hole)

	# 窓の穴をくり抜く(CSGBox3D)
	var window_hole = CSGBox3D.new()
	window_hole.size = Vector3(2, 1.5, 1.5)
	window_hole.position = Vector3(-3, 3, 0)  # 壁の左上に配置
	window_hole.operation = CSGShape3D.OPERATION_SUBTRACTION  # 減算演算
	wall.add_child(window_hole)

	print("壁にドアと窓がくり抜かれました")

CSGの仲間たち

CSGBox3D だけでなく、複数のプリミティブが用意されています:

CSGノード形状主要プロパティ用途例
CSGBox3D立方体size壁、床、建築物
CSGSphere3D球体radius, radial_segments, rings爆発範囲、丸い装飾
CSGCylinder3D円柱radius, height柱、パイプ、筒状オブジェクト
CSGMesh3D任意のメッシュmesh複雑な形状の加工
CSGCombiner3D複合形状の親なし(コンテナ)複数のCSGを統合

CSGCombiner3D を使った複合形状の作り方

複数のCSGノードを組み合わせる場合、CSGCombiner3D を親として使うと整理しやすくなります:


extends Node3D

func _ready():
	# CSGCombiner3D(複合体の親)
	var combiner = CSGCombiner3D.new()
	add_child(combiner)

	# 基盤(床)
	var base = CSGBox3D.new()
	base.size = Vector3(5, 0.5, 5)
	base.position = Vector3(0, 0, 0)
	base.operation = CSGShape3D.OPERATION_UNION
	combiner.add_child(base)

	# 塔(中央)
	var tower = CSGCylinder3D.new()
	tower.radius = 1.0
	tower.height = 4.0
	tower.position = Vector3(0, 2, 0)
	tower.operation = CSGShape3D.OPERATION_UNION
	combiner.add_child(tower)

	# 球の装飾(塔の頂上)
	var decoration = CSGSphere3D.new()
	decoration.radius = 0.7
	decoration.position = Vector3(0, 4.5, 0)
	decoration.operation = CSGShape3D.OPERATION_UNION
	combiner.add_child(decoration)

	# コアをくり抜く(塔の内部)
	var core = CSGCylinder3D.new()
	core.radius = 0.6
	core.height = 4.5
	core.position = Vector3(0, 2, 0)
	core.operation = CSGShape3D.OPERATION_SUBTRACTION
	combiner.add_child(core)

	print("複合形状が作成されました")
CSGCombiner3Dによる複合形状の階層構造
CSGCombiner3D を使い複数のプリミティブを統合することで、複雑な形状が実現できます

もっと使いこなす:カスタマイズできるパラメータ

まずは基本を動かしてみてから、余裕が出たら試してみてください。

パラメータ設定値の例効果
smoothing_enabledtrue/falseスムーズシェーディング。true で滑らかな見た目
invert_facestrue/false面の向きを反転。内側を表示したい場合に使用
materialStandardMaterial3D など色・テクスチャなどの外観設定
collision_layer / mask1 〜 32複数のレイヤーで衝突判定を細かく制御
operationUNION / INTERSECTION / SUBTRACTION他のCSGとの演算方式を指定

本番環境への置き換え:MeshInstance3D + CollisionShape3D

プロトタイプから本番環境への移行では、CSGを MeshInstance3D に置き換えることが推奨されます。理由はパフォーマンス最適化です:


# CSGを使った設計完了後、本番用に置き換える例

# 方法1: CSGから静的メッシュをエクスポート
# Godot Editor で、CSGShape3D を右クリック → "メッシュをエクスポート"

# 方法2: プログラムで置き換え
func convert_csg_to_mesh(csg_node: CSGShape3D):
	var mesh_instance = MeshInstance3D.new()
	mesh_instance.mesh = csg_node.get_meshes()[1]  # CSGのメッシュを取得
	mesh_instance.material_override = csg_node.material

	var collision_shape = CollisionShape3D.new()
	collision_shape.shape = csg_node.get_collision_shape()

	return [mesh_instance, collision_shape]
CSG設計から最終MeshInstance3Dへの置き換え
開発ではCSGで素早く設計、本番ではMeshInstance3Dで最適化

まとめ

CSGBox3D とそのCSGファミリーは、3D環境のプロトタイピングを劇的に高速化するノードです。ブーリアン演算を活用することで、複雑な形状も直感的に設計できます。ただし本番環境ではパフォーマンスのため MeshInstance3D への置き換えが推奨されます。

  • OPERATION_UNION(加算)・SUBTRACTION(減算)・INTERSECTION(交差)を使い分けることで、複雑な形状が簡単に作成できる
  • use_collision を有効化することで、CSG形状そのものが衝突判定として機能
  • CSGCombiner3D で複数のプリミティブを統合し、整理された階層構造を作る
  • 開発完了後は、パフォーマンス最適化のため MeshInstance3D への置き換えを検討

次回は GridMap について解説します。タイルベースの3D環境を効率的に構築するノードです。

この記事はGodot 4.xをもとに執筆しています。

関連性の高いノード解説記事

コメント