Por qué importan las capas de colisión
Las capas de colisión son la base de todas las interacciones físicas en Godot 4 — movimiento, detección de impactos, raycasting, disparadores de Area y mucho más. Entender la diferencia entre Layer y Mask es crucial, y malinterpretarla es uno de los tropiezos más comunes tanto para principiantes como para desarrolladores experimentados.
Layer vs Mask — El modelo mental
Cada objeto físico en Godot tiene dos propiedades de máscara de bits:
- Layer = "existo en estas capas" (lo que soy)
- Mask = "escaneo estas capas" (lo que puedo ver / golpear)
Regla clave
A colisiona con B cuando la máscara de A incluye la capa de B O la máscara de B incluye la capa de A. Basta con que uno de los lados "vea" al otro para que se produzca una colisión.
Nombrar las capas en la configuración del proyecto
Antes de escribir cualquier código, ponles nombre a tus capas. Esto hace que el Inspector sea mucho más fácil de usar y evita confusiones a medida que tu proyecto crece.
Configuración del proyecto > Nombres de capas > Física 2D (o Física 3D):
| Capa n.º | Nombre | Propósito |
|---|---|---|
| 1 | Player | El personaje del jugador |
| 2 | Enemy | Todos los cuerpos enemigos |
| 3 | Environment | Muros, suelos, plataformas |
| 4 | Projectile | Balas, flechas, hechizos |
| 5 | Pickup | Objetos, monedas, botiquines |
| 6 | Trigger | Sensores, zonas de aparición, puntos de control |
Configurar capas por código (GDScript)
Godot 4 ofrece dos enfoques — la API basada en valores (recomendada) y la asignación directa de la máscara de bits:
# 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)
Truco de la máscara de bits
Los números de capa empiezan en 1 en set_collision_layer_value(), pero la máscara de bits subyacente empieza en 0. Capa 1 = bit 0 = valor 1, Capa 2 = bit 1 = valor 2, Capa 3 = bit 2 = valor 4. Ante la duda, usa la API basada en valores para evitar errores.
Esquemas de capas comunes
Plataformas / Scroll lateral
| Objeto | Layer | Mask | Explicación |
|---|---|---|---|
| Player | 1 | 2, 3, 5, 6 | Detecta enemigos, entorno, objetos y disparadores |
| Enemy | 2 | 1, 3 | Detecta al jugador y el entorno |
| Environment | 3 | — | Pasivo — detectado por otros |
| Projectile | 4 | 2, 3 | Golpea a enemigos y muros |
| Pickup | 5 | — | Pasivo — el jugador lo detecta |
| Trigger | 6 | 1 | Detecta solo al jugador |
Cenital / Roguelike
| Objeto | Layer | Mask | Explicación |
|---|---|---|---|
| Player | 1 | 2, 3, 5, 6 | Detecta enemigos, muros, NPCs y sensores |
| Enemy | 2 | 1, 3 | Detecta al jugador y los muros |
| Wall | 3 | — | Pasivo |
| Bullet | 4 | 1, 2, 3 | Golpea al jugador, a los enemigos y a los muros |
| NPC | 5 | 3 | Colisiona solo con los muros |
| Sensor | 6 | 1 | Detecta la entrada del jugador |
Capas de Area2D / Area3D
Las Areas usan el mismo sistema de Layer/Mask. Además, tienen dos propiedades de conmutación:
-
monitoring— Si estrue, esta Area detecta activamente otros objetos que entran en ella. -
monitorable— Si estrue, otras Areas pueden detectar esta Area.
Señales: area_entered vs body_entered
body_entered se dispara cuando un PhysicsBody (CharacterBody, RigidBody, StaticBody) entra en la Area. area_entered se dispara cuando entra otra Area. Asegúrate de conectar la señal correcta según tu 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 colisión de RayCast
Los nodos RayCast solo tienen Mask (sin Layer) porque son detectores, no cuerpos físicos. Configura la máscara para filtrar lo que el rayo puede golpear:
# 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
Ejemplo práctico: Player – Enemy – Projectile
Aquí tienes una configuración de capas completa para un juego de acción típico. Los comentarios muestran el razonamiento detrás de cada decisión:
# 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
Consejo: prevención del fuego amigo
Fíjate en que las balas del jugador enmascaran la capa 2 (Enemy) pero no la capa 1 (Player), y las balas enemigas enmascaran la capa 1 (Player) pero no la capa 2 (Enemy). Así es como se evita el fuego amigo puramente mediante la configuración de capas — sin necesidad de código.
Consejos de depuración
- Formas de colisión visibles: en el editor, ve a Depurar > Formas de colisión visibles para renderizar todas las formas de colisión en tiempo de ejecución. Esto revela de inmediato colisionadores que faltan o están mal alineados.
- Comprobación en el Inspector: selecciona un nodo y expande Collision > Layer y Collision > Mask en el Inspector. Pasa el cursor sobre cada bit para ver su nombre (si los nombraste en la configuración del proyecto).
-
Imprimir en tiempo de ejecución:
print("Layer: ", collision_layer, " Mask: ", collision_mask)para verificar los valores de la máscara de bits durante la partida.
Cambios de migración de 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) |
El parámetro bit empezaba en 0
|
El parámetro layer empieza en 1
|
| 20 capas disponibles | 32 capas disponibles |
Trampa de la migración
Si estás portando un proyecto de Godot 3, recuerda que set_collision_layer_bit(0, true) se convierte en set_collision_layer_value(1, true). El índice se desplaza en +1. Si se te pasa esto, todas tus capas quedarán desplazadas en uno.
Errores comunes
1. Olvidar configurar la Mask
Tu objeto tiene una Layer pero la Mask está vacía (todo ceros). El objeto existe en el mundo físico pero no detecta nada. Otros objetos con máscaras coincidentes seguirán detectándolo a él, pero move_and_slide() en este objeto lo atravesará todo.
2. Confundir Layer con Mask
Poner la Layer del jugador en 2 (Enemy) en lugar de su Mask. Ahora el jugador es un enemigo a ojos del motor de física. Recuerda siempre: Layer = lo que soy, Mask = lo que escaneo.
3. Usar valores de máscara de bits en lugar de números de capa
Escribir set_collision_layer_value(4, true) pensando que configura el valor de máscara de bits 4 (capas 1+2). En realidad, activa la capa 4. La API basada en valores toma números de capa, no valores de bit.
4. Detección unidireccional cuando se espera bidireccional
El objeto A enmascara la capa de B, pero B no enmascara la capa de A. move_and_slide() en A colisionará con B, pero move_and_slide() en B atravesará a A. Para que dos nodos CharacterBody se bloqueen mutuamente, ambos necesitan tener la capa del otro en su máscara.
Automatiza la configuración de física con Godot MCP Pro
Deja de activar casillas de capas manualmente. Deja que la IA configure toda tu colisión en segundos — incluyendo el nombrado de capas, la asignación de máscaras y la adición de raycasts.
Consigue Godot MCP Pro — $15setup_collision
set_physics_layers
get_physics_layers
get_collision_info
add_raycast