Preventing multiple collisions between 2 CharacterBody2D instances

Godot Version

4.2.1

Question

I have two CharacterBody2D nodes, one for the “Player” and one for the “Target”.

every time the “Player” collides with the “Target”, the score increments by 1 point.

I have the basic mechanic working, but if the Player is moving towards the target when they collide, Godot fires off two collisions.

I think I understand what’s happening here: The Target hasn’t moved far enough away from the Player on the next frame, so Godot detects another collision.

Here’s my question: Is there a simple way to prevent multiple collisions happening for this example?

The way I plan to fix this seems like overkill, but I’ll explain it here in the event that someone knows of a simpler way.

The first time a collision between the player and the target is detected, I will turn off collisions (by updating the collision layer for one of the nodes) until they are far enough apart from each other that it is safe to turn collisions back on.

I suspect I may unaware of some setting that would fix this issue without me needing to code around it.

If anyone want’s to see the collision detection code I’m using right now, here it is. One caveat to be aware of. I’ve implemented my own Redux style state management system, that’s what Gdux is.

This script is attached to the Target, not the Player.

func _physics_process(delta: float)->void:
	var _delta := delta * speed
    # This script is an @tool script because I do some custom drawing tat I need to see in the editor
	if !Engine.is_editor_hint():
		vel.y += gravity * _delta
		var collision := move_and_collide(vel*_delta)	
		if collision:
			var collider := collision.get_collider() as Node2D
			if (collider).is_in_group('world_collider'):
				vel = vel.bounce(collision.get_normal())
			
			if (collider).is_in_group('ground_collider'):
				Gdux.dispatch(GameActions.ground_hit_action())
				vel = vel.bounce(collision.get_normal())
			
			if (collider).is_in_group('player_collider'):
				Gdux.dispatch(GameActions.player_hit_action())
				vel = vel.bounce(collision.get_normal())
				var p := collider.position
				vel.x = (p.x - collision.get_position().x) * -25
				vel.y = -1500

Any advice is greatly appreciated.

This is called debouncing. You could put a cool down timer to prevent the point to happen again. You could monitor velocities to make a threshold for the power of the collisions.

You can make an extended collision area to detect when the object is out of range.