Why Collision Layers Matter コリジョンレイヤーが重要な理由

Collision layers are the foundation of all physics interactions in Godot 4 — movement, hit detection, raycasting, area triggers, and more. Understanding the difference between Layer and Mask is crucial, and misunderstanding it is one of the most common pain points for beginners and experienced developers alike. コリジョンレイヤーは Godot 4 における全ての物理インタラクション(移動、ヒット判定、レイキャスト、Area トリガーなど)の基盤です。LayerMask の違いを正しく理解することは極めて重要で、これを誤解することが初心者にも経験者にも最もよくある落とし穴の一つです。

Layer vs Mask — The Mental Model Layer vs Mask — 考え方

Every physics object in Godot has two bitmask properties: Godot のすべての物理オブジェクトは 2 つのビットマスクプロパティを持ちます:

Key Rule 重要なルール

A collides with B when A's mask includes B's layer OR B's mask includes A's layer. Only one side needs to "see" the other for a collision to occur. A と B が衝突するのは、A の Mask に B の Layer が含まれている、または B の Mask に A の Layer が含まれている場合です。片方が相手を「見て」いれば衝突は発生します。

Naming Layers in Project Settings プロジェクト設定でレイヤーに名前をつける

Before writing any code, name your layers. This makes the Inspector far easier to use and prevents confusion as your project grows. コードを書く前に、まずレイヤーに名前をつけましょう。インスペクターが格段に使いやすくなり、プロジェクトが大きくなっても混乱を防げます。

Project Settings > Layer Names > 2D Physics (or 3D Physics): プロジェクト設定 > レイヤー名 > 2D 物理(または 3D 物理):

Layer #レイヤー番号 Name名前 Purpose用途
1PlayerThe player characterプレイヤーキャラクター
2EnemyAll enemy bodies全ての敵キャラクター
3EnvironmentWalls, floors, platforms壁、床、プラットフォーム
4ProjectileBullets, arrows, spells弾丸、矢、魔法
5PickupItems, coins, health packsアイテム、コイン、回復パック
6TriggerSensors, spawn zones, checkpointsセンサー、スポーンゾーン、チェックポイント

Setting Layers in Code (GDScript) コードでレイヤーを設定する (GDScript)

Godot 4 provides two approaches — the value-based API (recommended) and direct bitmask assignment: Godot 4 では 2 つの方法があります — 値ベースの API(推奨)と、ビットマスクの直接代入です:

# Godot 4 API — value-based (1-indexed, recommended)
set_collision_layer_value(1, true)   # I am on layer 1
set_collision_mask_value(2, true)    # I detect layer 2

# Or use bitmask directly
collision_layer = 1   # Layer 1 only (bit 0)
collision_mask = 6    # Layers 2 and 3 (bits 1 + 2 = 6)

# Read current state
var on_layer_1: bool = get_collision_layer_value(1)
var scans_layer_2: bool = get_collision_mask_value(2)

Bitmask Gotcha ビットマスクの注意点

Layer numbers are 1-based in set_collision_layer_value(), but the underlying bitmask is 0-based. Layer 1 = bit 0 = value 1, Layer 2 = bit 1 = value 2, Layer 3 = bit 2 = value 4. When in doubt, use the value-based API to avoid mistakes. set_collision_layer_value() のレイヤー番号は 1始まり ですが、内部のビットマスクは 0始まり です。レイヤー1 = bit 0 = 値 1、レイヤー2 = bit 1 = 値 2、レイヤー3 = bit 2 = 値 4。迷ったら値ベースの API を使いましょう。

Common Layer Schemes よくあるレイヤー構成例

Platformer / Side-scroller プラットフォーマー / 横スクロール

Objectオブジェクト Layer Mask Explanation説明
Player12, 3, 5, 6Detects enemies, environment, pickups, triggers敵、環境、アイテム、トリガーを検出
Enemy21, 3Detects player and environmentプレイヤーと環境を検出
Environment3Passive — detected by others受動的 — 他から検出される
Projectile42, 3Hits enemies and walls敵と壁に当たる
Pickup5Passive — player detects it受動的 — プレイヤーが検出
Trigger61Detects player onlyプレイヤーのみ検出

Top-down / Roguelike トップダウン / ローグライク

Objectオブジェクト Layer Mask Explanation説明
Player12, 3, 5, 6Detects enemies, walls, NPCs, sensors敵、壁、NPC、センサーを検出
Enemy21, 3Detects player and wallsプレイヤーと壁を検出
Wall3Passive受動的
Bullet41, 2, 3Hits player, enemies, and wallsプレイヤー、敵、壁に当たる
NPC53Collides with walls only壁のみと衝突
Sensor61Detects player entryプレイヤーの進入を検出

Area2D / Area3D Layers Area2D / Area3D のレイヤー

Areas use the same Layer/Mask system. Additionally, they have two toggle properties: Area も同じ Layer/Mask システムを使います。さらに 2 つのトグルプロパティがあります:

Signals: area_entered vs body_entered シグナル: area_entered vs body_entered

body_entered fires when a PhysicsBody (CharacterBody, RigidBody, StaticBody) enters the Area. area_entered fires when another Area enters. Make sure you connect the right signal for your use case. body_enteredPhysicsBody(CharacterBody、RigidBody、StaticBody)が Area に入った時に発火します。area_entered別の Area が入った時に発火します。用途に合ったシグナルを接続してください。

# Pickup Area2D — detect when the Player body enters
func _ready() -> void:
    body_entered.connect(_on_body_entered)

func _on_body_entered(body: Node2D) -> void:
    if body.is_in_group("player"):
        collect()
        queue_free()

RayCast Collision Mask RayCast のコリジョンマスク

RayCast nodes only have a Mask (no Layer) because they are detectors, not physical bodies. Set the mask to filter what the ray can hit: RayCast ノードには Mask のみがあります(Layer はありません)。検出器であり物理ボディではないためです。Mask を設定してレイの衝突対象をフィルタリングします:

# RayCast that only detects enemies (layer 2)
$RayCast2D.collision_mask = 2  # Layer 2 = Enemy
# Or use the value-based API:
$RayCast2D.set_collision_mask_value(1, false)  # Ignore Player
$RayCast2D.set_collision_mask_value(2, true)   # Detect Enemy
$RayCast2D.set_collision_mask_value(3, false)  # Ignore Environment

# Line-of-sight ray that ignores projectiles
$LineOfSight.collision_mask = 0
$LineOfSight.set_collision_mask_value(1, true)  # Player
$LineOfSight.set_collision_mask_value(3, true)  # Environment

Practical Example: Player – Enemy – Projectile 実践例: Player – Enemy – Projectile

Here is a complete layer setup for a typical action game. Comments show the reasoning behind each choice: 典型的なアクションゲーム向けの完全なレイヤー設定です。各選択の理由をコメントで示します:

# Player (CharacterBody2D)
# Layer: 1 (Player)          — "I am the player"
# Mask: 2 (Enemy), 3 (Environment), 5 (Pickup)
#   — I collide with enemies, walls, and can pick up items

# Enemy (CharacterBody2D)
# Layer: 2 (Enemy)            — "I am an enemy"
# Mask: 1 (Player), 3 (Environment)
#   — I collide with the player and walls

# Player Bullet (Area2D)
# Layer: 4 (Projectile)       — "I am a projectile"
# Mask: 2 (Enemy), 3 (Environment)
#   — I hit enemies and walls, but NOT the player who fired me

# Enemy Bullet (Area2D)
# Layer: 4 (Projectile)       — "I am a projectile"
# Mask: 1 (Player), 3 (Environment)
#   — I hit the player and walls, but NOT the enemy who fired me

Tip: Friendly Fire Prevention ヒント: フレンドリーファイアの防止

Notice that Player Bullets mask layer 2 (Enemy) but not layer 1 (Player), and Enemy Bullets mask layer 1 (Player) but not layer 2 (Enemy). This is how you prevent friendly fire purely through layer configuration — no code needed. Player Bullet はレイヤー2(Enemy)をマスクしますがレイヤー1(Player)はマスクしません。Enemy Bullet はレイヤー1(Player)をマスクしますがレイヤー2(Enemy)はマスクしません。これがレイヤー設定だけでフレンドリーファイアを防ぐ方法です — コード不要です。

Debugging Tips デバッグのヒント

Godot 3 → 4 Migration Changes Godot 3 → 4 の移行変更点

Godot 3 Godot 4
set_collision_layer_bit(bit, value) set_collision_layer_value(layer, value)
set_collision_mask_bit(bit, value) set_collision_mask_value(layer, value)
bit parameter was 0-based bit パラメータは 0始まり layer parameter is 1-based layer パラメータは 1始まり
20 layers available 20 レイヤー使用可能 32 layers available 32 レイヤー使用可能

Migration Pitfall 移行時の落とし穴

If you are porting a Godot 3 project, remember that set_collision_layer_bit(0, true) becomes set_collision_layer_value(1, true). The index shifts by +1. Miss this and all your layers will be off by one. Godot 3 プロジェクトを移植する場合、set_collision_layer_bit(0, true)set_collision_layer_value(1, true) になります。インデックスが +1 ずれます。これを見落とすと全てのレイヤーが 1 つずれてしまいます。

Common Mistakes よくあるミス

1. Forgetting to set the Mask 1. Mask の設定忘れ

Your object has a Layer but Mask is empty (all zeros). The object exists in the physics world but does not detect anything. Other objects with matching masks will still detect it, but move_and_slide() on this object will pass through everything. オブジェクトに Layer はあるが Mask が空(全てゼロ)。オブジェクトは物理世界に存在しますが、何も検出しません。マスクが一致する他のオブジェクトからは検出されますが、このオブジェクトの move_and_slide() は全てをすり抜けます。

2. Confusing Layer with Mask 2. Layer と Mask の混同

Setting the Player's Layer to 2 (Enemy) instead of its Mask. Now the player is an enemy as far as the physics engine is concerned. Always remember: Layer = what I am, Mask = what I scan. プレイヤーの Mask ではなく Layer を 2(Enemy)に設定してしまう。物理エンジンからするとプレイヤーが敵になってしまいます。常に覚えておきましょう:Layer = 自分が何か、Mask = 何をスキャンするか。

3. Using bitmask values instead of layer numbers 3. レイヤー番号の代わりにビットマスク値を使う

Writing set_collision_layer_value(4, true) thinking it sets bitmask value 4 (layers 1+2). In reality, it enables layer 4. The value-based API takes layer numbers, not bit values. set_collision_layer_value(4, true) でビットマスク値 4(レイヤー1+2)を設定したつもりが、実際にはレイヤー4を有効にしています。値ベースの API はビット値ではなくレイヤー番号を取ります。

4. One-way detection when bidirectional is expected 4. 双方向を期待しているのに片方向だけ検出される

Object A masks B's layer but B does not mask A's layer. move_and_slide() on A will collide with B, but move_and_slide() on B will pass through A. For two CharacterBody nodes to block each other, both need the other's layer in their mask. A が B のレイヤーをマスクしているが、B は A のレイヤーをマスクしていない。A の move_and_slide() は B と衝突しますが、B の move_and_slide() は A をすり抜けます。2 つの CharacterBody が互いにブロックするには、両方が相手のレイヤーを自分のマスクに含める必要があります。

Automate Physics Setup with Godot MCP Pro Godot MCP Pro で物理設定を自動化

Stop manually toggling layer checkboxes. Let AI configure your entire collision setup in seconds — including naming layers, assigning masks, and adding raycasts. レイヤーのチェックボックスを手動で切り替えるのはやめましょう。AI がレイヤーの命名、マスクの割り当て、レイキャストの追加を含むコリジョン設定全体を数秒で構成します。

Get Godot MCP Pro — $5 Godot MCP Pro を入手 — $5
Related tools: 関連ツール: setup_collision set_physics_layers get_physics_layers get_collision_info add_raycast