Por que as camadas de colisão importam

As camadas de colisão são a base de todas as interações físicas no Godot 4 — movimento, detecção de acerto, raycasting, gatilhos de área e muito mais. Entender a diferença entre Layer e Mask é crucial, e confundi-las é um dos problemas mais comuns tanto para iniciantes quanto para desenvolvedores experientes.

Layer vs Mask — O modelo mental

Todo objeto físico no Godot tem duas propriedades de bitmask:

Regra fundamental

A colide com B quando a máscara de A inclui a camada de B OU a máscara de B inclui a camada de A. Basta que um dos lados "veja" o outro para que a colisão ocorra.

Nomeando camadas nas Configurações do Projeto

Antes de escrever qualquer código, nomeie suas camadas. Isso torna o Inspetor muito mais fácil de usar e evita confusão à medida que seu projeto cresce.

Configurações do Projeto > Nomes de Camadas > Física 2D (ou Física 3D):

Camada nº Nome Finalidade
1PlayerO personagem do jogador
2EnemyTodos os corpos inimigos
3EnvironmentParedes, pisos, plataformas
4ProjectileBalas, flechas, feitiços
5PickupItens, moedas, kits de vida
6TriggerSensores, zonas de spawn, checkpoints

Definindo camadas em código (GDScript)

O Godot 4 oferece duas abordagens — a API baseada em valores (recomendada) e a atribuição direta de bitmask:

# 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)

Pegadinha do bitmask

Os números de camada são baseados em 1 em set_collision_layer_value(), mas o bitmask subjacente é baseado em 0. Camada 1 = bit 0 = valor 1, Camada 2 = bit 1 = valor 2, Camada 3 = bit 2 = valor 4. Na dúvida, use a API baseada em valores para evitar erros.

Esquemas de camadas comuns

Plataforma / Side-scroller

Objeto Layer Mask Explicação
Player12, 3, 5, 6Detecta inimigos, ambiente, itens, gatilhos
Enemy21, 3Detecta o jogador e o ambiente
Environment3Passivo — detectado pelos outros
Projectile42, 3Atinge inimigos e paredes
Pickup5Passivo — o jogador o detecta
Trigger61Detecta apenas o jogador

Top-down / Roguelike

Objeto Layer Mask Explicação
Player12, 3, 5, 6Detecta inimigos, paredes, NPCs, sensores
Enemy21, 3Detecta o jogador e paredes
Wall3Passivo
Bullet41, 2, 3Atinge o jogador, inimigos e paredes
NPC53Colide apenas com paredes
Sensor61Detecta a entrada do jogador

Camadas de Area2D / Area3D

As Areas usam o mesmo sistema de Layer/Mask. Além disso, elas têm duas propriedades de alternância:

Sinais: area_entered vs body_entered

body_entered dispara quando um PhysicsBody (CharacterBody, RigidBody, StaticBody) entra na Area. area_entered dispara quando outra Area entra. Certifique-se de conectar o sinal correto para o seu caso de uso.

# 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()

Máscara de colisão do RayCast

Os nós RayCast têm apenas uma Mask (sem Layer), porque são detectores, não corpos físicos. Defina a máscara para filtrar o que o raio pode atingir:

# 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

Exemplo prático: Player – Enemy – Projectile

Aqui está uma configuração completa de camadas para um jogo de ação típico. Os comentários mostram o raciocínio por trás de cada escolha:

# 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

Dica: prevenção de fogo amigo

Observe que as balas do jogador mascaram a camada 2 (Enemy), mas não a camada 1 (Player), e as balas dos inimigos mascaram a camada 1 (Player), mas não a camada 2 (Enemy). É assim que você evita o fogo amigo apenas por meio da configuração de camadas — sem necessidade de código.

Dicas de depuração

Mudanças de migração do 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)
O parâmetro bit era baseado em 0 O parâmetro layer é baseado em 1
20 camadas disponíveis 32 camadas disponíveis

Armadilha da migração

Se você está portando um projeto do Godot 3, lembre-se de que set_collision_layer_bit(0, true) se torna set_collision_layer_value(1, true). O índice muda em +1. Ignore isso e todas as suas camadas ficarão deslocadas em uma posição.

Erros comuns

1. Esquecer de definir a Mask

Seu objeto tem uma Layer, mas a Mask está vazia (tudo zero). O objeto existe no mundo físico, mas não detecta nada. Outros objetos com máscaras correspondentes ainda vão detectá-lo, mas o move_and_slide() deste objeto atravessará tudo.

2. Confundir Layer com Mask

Definir a Layer do jogador como 2 (Enemy) em vez de sua Mask. Agora o jogador é um inimigo do ponto de vista do motor de física. Lembre-se sempre: Layer = o que eu sou, Mask = o que eu examino.

3. Usar valores de bitmask em vez de números de camada

Escrever set_collision_layer_value(4, true) achando que isso define o valor de bitmask 4 (camadas 1+2). Na verdade, ele habilita a camada 4. A API baseada em valores recebe números de camada, não valores de bit.

4. Detecção unidirecional quando se espera bidirecional

O objeto A mascara a camada de B, mas B não mascara a camada de A. O move_and_slide() de A colidirá com B, mas o move_and_slide() de B atravessará A. Para que dois nós CharacterBody bloqueiem um ao outro, ambos precisam ter a camada do outro em sua máscara.

Automatize a configuração de física com o Godot MCP Pro

Pare de alternar caixas de seleção de camadas manualmente. Deixe a IA configurar toda a sua configuração de colisão em segundos — incluindo nomear camadas, atribuir máscaras e adicionar raycasts.

Obter o Godot MCP Pro — $15
Ferramentas relacionadas: setup_collision set_physics_layers get_physics_layers get_collision_info add_raycast