Best Practice for Detecting Area2Ds that change monitorable status?

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

I’m making a game that uses the light2D system in Godot 3.5.1 (I’m not interested in moving to Godot 4 at this time).

Currently I’m making the system by which an object can ‘sense’ whether it is in a light, which isn’t possible with Light2D in Godot 3.5 so I’m just setting up a system of Area2Ds to specify where the lights shine. The class I’m building to sense this I’m calling the light_sensor class.

I had been using the on_area_entered() signals from the Area2D of the sensor to keep a list of lights currently shining on the light_sensor. The issue is, if I allow a light that is off (I turn lights off by turning off ‘monitorable’ on the sensable Area2D) to overlap with a sensor’s area, and then I turn the light on, the on_area_entered() signal doesn’t go off.

So my question is, is there a best practice to use when dealing with an issue like this? I thought to check continually every frame using Area2D.get_overlapping_areas(). This doesn’t work at all. I have to physically move the light in order to get the sensor to pick up that something has changed. Does anyone have any ideas?

Thank you very much.

:bust_in_silhouette: Reply From: aidave

The solution is get_overlapping_areas every frame, which you said you tried, but maybe you don’t have the right collision layers/masks or monitor flags set for them to be detected. Also you are supposed to wait a frame after setting monitorable to true (use set_deferred)

Weird, it doesn’t seem to work. I created a scene from scratch with two area2Ds, a ‘sensor’ and a ‘sensable’. I left both with the default collision layer/mask and made the sensable object able to move around.

Sensor code:

func _physics_process(delta):
var areas = get_overlapping_areas()
if areas.size() > 0:
	visualdebug.reticule(global_position, .1, Color.crimson)

Sensable code (other than movement):

func _physics_process(delta):
if Input.is_action_just_pressed("test_input_1"):
	set_deferred("monitorable", !monitorable)
	$Sprite.visible = !$Sprite.visible

(I don’t know why the indentation is messed up when I post it)

The visualdebug.reticule() call draws an x onscreen. So it should draw whenever the sensor is in the sensable area if I understand correctly. But it’s the same as before. I put the sensor in the middle of the sensable object, the x is being drawn:

then I press the button to make it not monitorable, and the x stays there:

Of course if I turn monitorable off or on when the sensor is outside the sensable area and then enter, it works fine.

I’m not sure. Can you see anything wonky I’m doing?

rainswell | 2023-03-31 18:55

You should share your project in a ZIP file here

aidave | 2023-04-01 09:42