How to set collision mask for intersect_shape?

Godot Version

4.4.1

Question

Hi everyone!

I’m trying to use the function intersect_shape to query bodies on layer 2. However, when I set the collision_mask attribute to 2, the query gets bodies on other layers except the one expected. What am I doing wrong?

Here’s the piece of code where I run the query:

extends Sprite2D
class_name Bullet

var speed: float
var speed_curve: Curve
var speed_randomized: float
var direction: Vector2
var time: float
var lifetime: float
var collision_mask: int = 1

@export var shape: Shape2D
var query := PhysicsShapeQueryParameters2D.new()
@onready var state := get_world_2d().direct_space_state 

func _ready() -> void:
	query.set_shape(shape)
	query.collide_with_bodies = true

func _process(delta):
	time += 0.01
	if time > lifetime:
		finish()

	position += direction * speed * delta * speed_curve.sample(time) * speed_randomized

	query.collision_mask = collision_mask
	query.transform = global_transform
	var result = state.intersect_shape(query, 1)
	if result:
		for i in result.size():
			if result[i].collider.name == "Player":
				result[i].collider.on_hit()
		finish()
		
func finish():
	set_process_mode(PROCESS_MODE_DISABLED)
	hide()

Source code: Making sure you're not a bot!

PhysicsShapeQueryParameters2D.collision_mask is a bitmask so you may not be setting the correct value.

I saw in your project that you are using @export to set the mask. Try using @export_flags_2d_physics instead.

@mrcdk, thanks for the reply! I applied your suggestion and it helped me, but I realized the problem may be another…

When I set my Player on the editor, it shows correctly that it is on the layer 2.

However, during runtime, it shows it is on the layer 1…

Do you have any idea of what might it be?

I believe the problem was cache-related or some engine behaviour I’m not aware of. The collision layer was resetting to 1.

  • I opened the scene and the Player collision layer was set to 1.
  • I set it to layer 2 and saved the scene.
  • I reopened the scene and the Player collision layer was set to 1 again, ignoring previous set.
  • I set the collision to 2 again.
  • I cut the Player node and re-paste it to the tree.
  • I reopen the scene and now it is correctly set to layer 2.

My Player is an instance of a scene, and in the original scene the collision layer is not set, therefore having value 1. Wonder if that was causing the problem…

Now it is gladly solved, but I don’t now exactly what was causing it.