はじめに
Godot 4で3Dゲームを開発していると、「2Dゲームと同じようにマップを作りたい」と感じることがあります。Godot 2Dにはタイルベースのマップ制作に便利なTileMapノードがありますが、3D版はどうでしょう?それが今回解説するGridMapです。
GridMapを使うと、3D空間上に「格子状に配置したメッシュ」のマップを効率よく作成できます。ダンジョン、パズルゲーム、ボクセル風の世界——複数のシーンを繰り返し配置する場面で、GridMapの価値が光ります。
GridMapとは?
GridMapは、MeshLibraryという「タイルセット」を使って、3D空間に「メッシュを格子状に配置」するノードです。一言で言えば「3D版TileMap」です。
継承ツリー:
GridMap → Node3D → Node → Object
GridMapの核となるのはMeshLibraryリソース(`.meshlib`)です。これは「ID → メッシュ+コライダー」のマッピングを保持するリソースで、一度定義すればGridMapで何度も再利用できます。TileMapの「タイルセット」と似た役割を果たします。
配置の方法は2つあります。
- エディタUI:Godotエディタの3Dビューポートで、GridMapツールを使って対話的に配置
- スクリプト:GDScriptで
set_cell_item()を呼んで動的に配置
また、GridMapは自動的に複数セルのコライダーを統合し、パフォーマンスの良い物理シミュレーションを実現します。

このノードを使うべき場面
使う場面:
- ダンジョンやステージ制作:同じサイズの立方体や部屋を並べて大規模な3D環境を効率よく構築
- ボクセル風ゲーム:キューブやボクセルをGridMapで配置し、Minecraftのような見た目を実現
- 3D謎解きパズル:動く/消える/変わるタイルを組み合わせたパズルの実装
- プロシージャル3Dレベル生成:スクリプトで自動的にセルを配置してダンジョンを生成
- 3Dローグライク:部屋単位でレベルを組み立てるダンジョンクローラー
使わない場面:
- 複雑で自由な形状の3D環境:GridMapは格子を前提とするため、有機的な曲線や複雑な地形には向きません。3DモデルのインポートやCSGノードの方が適切です
- 異なるサイズのメッシュを混在:GridMapは統一サイズのセルで機能するため、複数の大きさを混在させるとレイアウトが歪みます
主なプロパティと機能
| プロパティ | 型 | 説明 | デフォルト |
|---|---|---|---|
mesh_library |
MeshLibrary | 使用するタイルセット。エディタで割り当てるか、スクリプトで動的に設定 | null |
cell_size |
Vector3 | 1セルのサイズ。通常は(1, 1, 1)や(2, 2, 2)など統一値 | (1, 1, 1) |
cell_octant_size |
int | オクツリーの分割数。物理演算の最適化に使用。8推奨 | 8 |
collision_layer |
int(ビットフラグ) | このGridMapがどのレイヤーに属するか | 1 |
collision_mask |
int(ビットフラグ) | どのレイヤーの物理オブジェクトと衝突するか | 1 |
主なメソッド:
# セルにメッシュを配置(または削除)
# 座標(x, y, z)にID item_idのメッシュを配置
set_cell_item(Vector3i(x, y, z), item_id, orientation)
# セルからメッシュを取得
# 座標(x, y, z)に置かれているメッシュのIDを返す
get_cell_item(Vector3i(x, y, z))
# 配置されているすべてのセル座標を取得(高速化に便利)
get_used_cells()
# セルを削除
clear_cell(Vector3i(x, y, z))
コード例1:エディタで配置したGridMapを読み込んで、プレイヤーの移動に応じて一部を変更
extends Node3D
@onready var grid_map = $GridMap
func _ready():
# GridMapが既に配置されていると仮定
# 特定のセルをクリアする
grid_map.clear_cell(Vector3i(0, 0, 0))
# 別のセルに別のアイテムを配置(回転あり)
grid_map.set_cell_item(Vector3i(1, 0, 0), 2, 0) # item_id=2, 回転なし
func _physics_process(delta):
# プレイヤーの座標からセル座標を算出
var player_pos = $Player.position
var cell_pos = Vector3i(player_pos / grid_map.cell_size)
# その座標に何が置かれているか確認
var item_id = grid_map.get_cell_item(cell_pos)
if item_id >= 0:
print("セル", cell_pos, "にはアイテム", item_id, "があります")
else:
print("セル", cell_pos, "は空です")
コード例2:スクリプトでダンジョンを自動生成(シンプルな例)
extends Node3D
@export var grid_width = 10
@export var grid_height = 10
@export var grass_tile_id = 0
@export var wall_tile_id = 1
@onready var grid_map = $GridMap
func _ready():
generate_dungeon()
func generate_dungeon():
for x in range(grid_width):
for z in range(grid_height):
# ランダムに床と壁を配置
var is_wall = randf() < 0.2 # 20%の確率で壁
var tile_id = wall_tile_id if is_wall else grass_tile_id
# y = 0(地面)に配置
grid_map.set_cell_item(Vector3i(x, 0, z), tile_id, 0)
もっと使いこなす:カスタマイズできるパラメータ
まずは基本を動かしてみてから、余裕が出たら試してみてください。
| パラメータ | 目的 | 実装例 |
|---|---|---|
cell_sizeを可変 |
セルの大きさを調整し、異なるスケールのゲームに対応 | grid_map.cell_size = Vector3(2, 3, 2)複数のGridMapを重ねて異なるサイズで利用 |
collision_layercollision_maskを細かく設定 |
レイヤーを分離し、プレイヤー・敵・動く床などを別々に制御 | grid_map.collision_layer = 2grid_map.collision_mask = 3(レイヤー0と1の物理オブジェクトと衝突) |
| 複数GridMapの組み合わせ | レイヤーごとに異なるMeshLibraryを使い分け(壁層、床層、デコ層など) | GridMapを3つ用意し、各々異なるmesh_libraryを設定。編集・管理が楽 |
get_used_cells()で反復処理 |
配置済みセルをすべて走査し、イベント処理やデータ保存 | for cell in grid_map.get_used_cells(): |
応用例:敵スポーンポイントの自動生成
extends Node3D
@onready var grid_map = $GridMap
@export var enemy_tile_id = 10 # MeshLibraryで敵スポーン用タイルと定義
func _ready():
spawn_enemies_on_marked_tiles()
func spawn_enemies_on_marked_tiles():
for cell in grid_map.get_used_cells():
var item_id = grid_map.get_cell_item(cell)
if item_id == enemy_tile_id:
# セル座標をワールド座標に変換
var spawn_pos = grid_map.to_global(cell * grid_map.cell_size)
var enemy = preload("res://Enemy.tscn").instantiate()
enemy.position = spawn_pos
add_child(enemy)
# 敵が配置されたら、そのセルをクリア
grid_map.clear_cell(cell)

まとめ
GridMapは「格子状に統一サイズのメッシュを配置する3Dマップ作成ツール」で、2D版TileMapの3D化です。MeshLibraryを使うことで効率的にタイルセットを管理でき、スクリプトでの動的生成にも向いています。
- MeshLibraryが肝:タイルセットを一元管理し、再利用性を高める
- エディタUIと スクリプト両対応:手動配置と自動生成を組み合わせた柔軟な開発が可能
- パフォーマンス重視:コライダーの自動統合など、大規模マップにも対応
次回は、3D空間上のパスを定義して、敵やカメラを滑らかに移動させる「Path3D」を解説します。

シリーズ:Godot 4 ノード解説
001〜040:各種ノード | 041~070:個別ノード解説
- 041: CanvasLayer
- 042: ParallaxLayer
- 043: Parallax2D
- 044: Control
- 045: PanelContainer
- 046: TabContainer
- 047: MarginContainer
- 048: AnimationPlayer
- 049: AnimationTree
- 050: Tween
- 051: CPUParticles2D
- 052: GPUParticles2D
- 053: Sprite2D
- 054: CharacterBody2D
- 055: RigidBody2D
- 056: StaticBody2D
- 057: Area2D
- 058: AudioStreamPlayer
- 059: AudioStreamPlayer2D
- 060: AudioStreamPlayer3D
- 061: MultiMeshInstance3D
- 062: MeshInstance3D
- 063: CSGBox3D
- 064: CSGMesh3D
- 065: OmniLight3D
- 066: GridMap
- 067: Path3D
- 068: PathFollow3D
- 069: NavigationAgent3D
- 070: Skeleton3D
この記事はGodot 4.xをもとに執筆しています。


コメント