How do I do initial set up when get_overlapping_areas() returns an empty array in _ready?

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

I have a scene called Area2DTest with an Area2D as the root node. I would like to be able to place several of these Area2DTest scenes under the root node of the project and have them tell me what is overlapping so that each node can do some internal set up depending on what they overlap. The scene has an area_entered signal that runs a function called _on_Area2DTest_area_entered.

Area2DTest has code as follows:

extends Area2D

func _ready():
	print(self, " _ready(), ", get_overlapping_areas())
	#if there's any overlapping areas, do some stuff here.
	#but get_overlapping_areas() always returns an empty array, so we can't. :(

func _process(_delta):
	print(self, " _process() ", get_overlapping_areas())
	
func _physics_process(_delta):
	print(self, " _physics_process() ", get_overlapping_areas())
	
func _on_Area2DTest_area_entered(_area):
	print(self, " _on_Area2DTest_area_entered() ", get_overlapping_areas())
	#get_overlapping_areas returns an array of overlapping areas - woohoo!
	#But _ready and the first _physics_process have already run.
    #Too late for doing various initialisations. :(

I place two of the Area2DTest scenes in the root scene like so:

  • Node
  • Area2DTest
  • Area2DTest2

I make sure their collision shapes are overlapping.

I get output as follows:

Area2DTest2:[Area2D:1257] _ready(), []
Area2DTest:[Area2D:1259] _ready(), []
Area2DTest2:[Area2D:1257] _physics_process() []
Area2DTest:[Area2D:1259] _physics_process() []
Area2DTest:[Area2D:1259] _on_Area2DTest_area_entered() [Area2DTest2:[Area2D:1257]]
Area2DTest2:[Area2D:1257] _on_Area2DTest_area_entered() [Area2DTest:[Area2D:1259]]
Area2DTest2:[Area2D:1257] _physics_process() [Area2DTest:[Area2D:1259]]
Area2DTest:[Area2D:1259] _physics_process() [Area2DTest2:[Area2D:1257]]
Area2DTest2:[Area2D:1257] _process() [Area2DTest:[Area2D:1259]]
Area2DTest:[Area2D:1259] _process() [Area2DTest2:[Area2D:1257]]

Note that each time I run it, _process prints its message at different times in the sequence, but the _on_Area2DTest_area_entered function always runs after _physics_process.

What this demonstrates is that I can’t rely on _ready, _process, or _physics_process to give me information I need to do initial set up for the scenes. I want to be able to display different things etc depending on what’s overlapping when scene first starts to run, so how do I do this? If I understand it correctly, the scene will already be displaying on screen for at least a frame before _on_Area2DTest_area_entered runs, so that’s useless.

I’d like a design pattern to address this problem. I just want to be able to create scenes within the editor by moving various nodes around and then when the project runs, they initialise themselves depending on what they’re overlapping.

I hope someone can help! Thank you!

:bust_in_silhouette: Reply From: Ertain

I think the collision detection is done in the _physics_process() function. A way to perform collision detection is to allow the _physics_process() function to run for a couple of frames. Try using something like yield(get_tree(), "physics_frame") before checking for overlapping areas.

Thanks. But what if I want the Area2D to know what it’s overlapping before it actually starts processing physics? E.g., what if there’s some critical setup that the Area2D needs to do on which code running within _physics_process is dependent? In my example above, _physics_process incorrectly says nothing is overlapping (i.e., get_overlapping_areas() returns an empty array).

E.g., The game starts and the game designer may have positioned the player for that level on ice or mud. Ice and mud are 2 different Area2Ds, as is the player. How the player node works within its _physics_process depends on what it is overlapping with. It can’t wait a frame or two for _get_overlapping_areas() to start working. It needs to know immediately.

gogodot77 | 2022-02-07 06:53

I don’t know what to do at that point. My only other suggestion is to do some primitive collision detection, e.g. use Rect2 and check for intersections.

Ertain | 2022-02-07 07:16