Pourquoi les calques de collision comptent
Les calques de collision sont le fondement de toutes les interactions physiques dans Godot 4 — déplacement, détection de collision, raycasting, déclencheurs de zone (Area) et plus encore. Comprendre la différence entre Layer et Mask est essentiel, et la mécomprendre est l'un des pièges les plus fréquents, aussi bien pour les débutants que pour les développeurs expérimentés.
Layer vs Mask — le modèle mental
Chaque objet physique dans Godot possède deux propriétés de type masque de bits :
- Layer = « J'existe sur ces calques » (ce que je suis)
- Mask = « Je scanne ces calques » (ce que je peux voir / toucher)
Règle fondamentale
A entre en collision avec B lorsque le Mask de A inclut le Layer de B OU que le Mask de B inclut le Layer de A. Il suffit qu'un seul côté « voie » l'autre pour qu'une collision se produise.
Nommer les calques dans les Paramètres du projet
Avant d'écrire la moindre ligne de code, nommez vos calques. Cela rend l'Inspecteur bien plus facile à utiliser et évite la confusion à mesure que votre projet grandit.
Paramètres du projet > Noms des calques > Physique 2D (ou Physique 3D) :
| N° de calque | Nom | Rôle |
|---|---|---|
| 1 | Player | Le personnage du joueur |
| 2 | Enemy | Tous les corps ennemis |
| 3 | Environment | Murs, sols, plateformes |
| 4 | Projectile | Projectiles, flèches, sorts |
| 5 | Pickup | Objets, pièces, kits de soin |
| 6 | Trigger | Capteurs, zones d'apparition, points de contrôle |
Définir les calques par le code (GDScript)
Godot 4 propose deux approches — l'API basée sur les valeurs (recommandée) et l'affectation directe du masque 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)
Piège du masque de bits
Les numéros de calque sont indexés à partir de 1 dans set_collision_layer_value(), mais le masque de bits sous-jacent est indexé à partir de 0. Calque 1 = bit 0 = valeur 1, calque 2 = bit 1 = valeur 2, calque 3 = bit 2 = valeur 4. En cas de doute, utilisez l'API basée sur les valeurs pour éviter les erreurs.
Schémas de calques courants
Plateformer / Défilement horizontal
| Objet | Layer | Mask | Explication |
|---|---|---|---|
| Player | 1 | 2, 3, 5, 6 | Détecte ennemis, environnement, objets, déclencheurs |
| Enemy | 2 | 1, 3 | Détecte le joueur et l'environnement |
| Environment | 3 | — | Passif — détecté par les autres |
| Projectile | 4 | 2, 3 | Touche les ennemis et les murs |
| Pickup | 5 | — | Passif — le joueur le détecte |
| Trigger | 6 | 1 | Détecte uniquement le joueur |
Vue de dessus / Roguelike
| Objet | Layer | Mask | Explication |
|---|---|---|---|
| Player | 1 | 2, 3, 5, 6 | Détecte ennemis, murs, PNJ, capteurs |
| Enemy | 2 | 1, 3 | Détecte le joueur et les murs |
| Wall | 3 | — | Passif |
| Bullet | 4 | 1, 2, 3 | Touche le joueur, les ennemis et les murs |
| NPC | 5 | 3 | N'entre en collision qu'avec les murs |
| Sensor | 6 | 1 | Détecte l'entrée du joueur |
Calques Area2D / Area3D
Les Areas utilisent le même système Layer/Mask. Elles disposent en plus de deux propriétés d'activation :
-
monitoring— Sitrue, cette Area détecte activement les autres objets qui y entrent. -
monitorable— Sitrue, d'autres Areas peuvent détecter cette Area.
Signaux : area_entered vs body_entered
body_entered se déclenche lorsqu'un PhysicsBody (CharacterBody, RigidBody, StaticBody) entre dans l'Area. area_entered se déclenche lorsqu'une autre Area y entre. Veillez à connecter le signal approprié à votre cas d'usage.
# 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()
Masque de collision RayCast
Les nœuds RayCast n'ont qu'un Mask (pas de Layer), car ce sont des détecteurs et non des corps physiques. Définissez le Mask pour filtrer ce que le rayon peut toucher :
# 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
Exemple pratique : Player – Enemy – Projectile
Voici une configuration de calques complète pour un jeu d'action typique. Les commentaires montrent le raisonnement derrière chaque choix :
# 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
Astuce : empêcher les tirs amis
Remarquez que les projectiles du joueur masquent le calque 2 (Enemy) mais pas le calque 1 (Player), et que les projectiles ennemis masquent le calque 1 (Player) mais pas le calque 2 (Enemy). C'est ainsi que l'on empêche les tirs amis uniquement par la configuration des calques — sans aucun code.
Conseils de débogage
- Formes de collision visibles : dans l'éditeur, allez dans Déboguer > Formes de collision visibles pour afficher toutes les formes de collision à l'exécution. Cela révèle immédiatement les colliders manquants ou mal alignés.
- Vérification dans l'Inspecteur : sélectionnez un nœud et développez Collision > Layer et Collision > Mask dans l'Inspecteur. Survolez chaque bit pour en voir le nom (si vous les avez nommés dans les Paramètres du projet).
-
Afficher à l'exécution :
print("Layer: ", collision_layer, " Mask: ", collision_mask)pour vérifier les valeurs du masque de bits pendant le jeu.
Changements de migration 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) |
Le paramètre bit était indexé à partir de 0
|
Le paramètre layer est indexé à partir de 1
|
| 20 calques disponibles | 32 calques disponibles |
Piège de migration
Si vous portez un projet Godot 3, souvenez-vous que set_collision_layer_bit(0, true) devient set_collision_layer_value(1, true). L'index est décalé de +1. Si vous oubliez cela, tous vos calques seront décalés d'un cran.
Erreurs courantes
1. Oublier de définir le Mask
Votre objet possède un Layer, mais le Mask est vide (que des zéros). L'objet existe dans le monde physique, mais ne détecte rien. Les autres objets dont les masques correspondent le détecteront quand même, mais move_and_slide() sur cet objet traversera tout.
2. Confondre Layer et Mask
Régler le Layer du joueur sur 2 (Enemy) au lieu de son Mask. Le joueur est désormais un ennemi du point de vue du moteur physique. Retenez toujours : Layer = ce que je suis, Mask = ce que je scanne.
3. Utiliser des valeurs de masque de bits au lieu de numéros de calque
Écrire set_collision_layer_value(4, true) en croyant définir la valeur de masque de bits 4 (calques 1+2). En réalité, cela active le calque 4. L'API basée sur les valeurs prend des numéros de calque, pas des valeurs de bits.
4. Détection à sens unique alors qu'on attend le bidirectionnel
L'objet A masque le Layer de B, mais B ne masque pas le Layer de A. move_and_slide() sur A entrera en collision avec B, mais move_and_slide() sur B traversera A. Pour que deux nœuds CharacterBody se bloquent mutuellement, il faut que les deux aient le calque de l'autre dans leur Mask.
Automatiser la configuration de la physique avec Godot MCP Pro
Fini de cocher manuellement les cases des calques. Laissez l'IA configurer toute votre installation de collision en quelques secondes — nommage des calques, affectation des masques et ajout de raycasts inclus.
Obtenir Godot MCP Pro — $15setup_collision
set_physics_layers
get_physics_layers
get_collision_info
add_raycast