How do I detect if a body stays in a collider?

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By camarones

I have a character (KinematicBody2D) that loses a life when it collides with an enemy (Rigidbody2D). To make this work, I have been using the Rigidbody2D body_entered() signal. However this doesn’t work if, for example the character was invincible when it collided with the enemy and then remains in contact until it is no longer invincible. This is because the body_entered() signal was only emitted once. According to old questions on forums, KinematicBody2D used to have an is_colliding() function, but that no longer seems to exist. How can I emit a signal every frame that the two bodies are in contact?

EDIT: Ideally I would like to be able to do this from the KinematicBody2D so I don’t have to call the function in every enemy.

:bust_in_silhouette: Reply From: Bartosz

You could use get_colliding_bodies() and process each colliding body accordingly to your use-case
see docs

The problem with get_colliding_bodies() is it only works for RigidBody. Ideally I want to be able to only in the player’s KinematicBody instead of once inside each enemy.

camarones | 2018-05-21 21:55

it looks like you would need to keep track of every object of your interest in some list and during enter and exit signal you would need to update it

Bartosz | 2018-05-21 21:59

:bust_in_silhouette: Reply From: camarones

Based on Bartosz’s comments, I have managed to get it to work!

In the enemy script:

func _on_body_entered(body):
	if body.is_in_group("Player"):
		body.colliding_enemies.append(self)

func _on_body_exited(body):
	if body.is_in_group("Player"):
		body.colliding_enemies.remove(body.colliding_enemies.find(self))

And in the player script:

func _physics_process(delta):
	#cycle through enemies we have collided with
	if !invincible && lives > 0:
		if colliding_enemies.size() > 0:
			take_damage(colliding_enemies[0].hit_damage)
			colliding_enemies[0].die()
			colliding_enemies.remove(0)