A continuation of this question,
The solution provided there by @Theraot works for _draw() but not for Area2D as you can see in this example:
script for player:
extends KinematicBody2D
var velocity: Vector2
func _physics_process(_delta):
velocity.y+=30
move_and_slide(velocity)
script for Holder:
extends Node2D
onready var item = $Item
onready var item_area = $ItemArea
onready var item_inital_offset = item.global_position - global_position
onready var area_inital_offset = item_area.global_position - item.global_position
var velocity: Vector2
func _body_entered(body):
print("body_entered=>", body)
func _body_exited(body):
print("body_exited=>", body)
func _physics_process(delta):
velocity.y+=30
global_position+=velocity * delta
item.global_position = global_position + item_inital_offset
item_area.global_position = item.global_position + area_inital_offset
func _ready():
item_area.connect("body_entered", self,"_body_entered")
item_area.connect("body_exited", self,"_body_exited")
when the Player (green) falls into the ItemArea (blue) and stops when it hits Item (red), the body_entered signal is not emitted even though you can clearly see that it entered the area
I have checked that the Area2D node works by initially placing another body in it and it emits a signal just fine
my best guess is that maybe since both Holder & Player are both falling at the same speed they technically never intersect but since Item is synced_with_physics there's a visual lag which makes it drag back and not take the ItemArea along with it
Edit
I tried using intersect_shape directly within Holder but it still didn't work:
extends Node2D
onready var item = $Item
onready var item_inital_offset = item.global_position - global_position
const SHAPE_OFFSET = Vector2(0, -52)
export(Shape2D) var intersect_shape: Shape2D
var intersecting_bodies := {}
var velocity: Vector2
func _body_entered(body):
print("body_entered=>", body)
func _body_exited(body):
print("body_exited=>", body)
func _physics_process(delta):
velocity.y+=30
global_position+=velocity * delta
item.global_position = global_position + item_inital_offset
check_area_process(delta)
update()
func check_area_process(_delta):
var space := get_world_2d().direct_space_state
var query := Physics2DShapeQueryParameters.new()
query.set_shape(intersect_shape)
query.transform = item.global_transform
query.transform.origin = item.global_position + SHAPE_OFFSET
var currently_intersecting_nodes:Array = space.intersect_shape(query)
var new_intersecting_bodies := {}
# check for newly entered objects
for node in currently_intersecting_nodes:
node=node.collider
new_intersecting_bodies[node]=null
if(!intersecting_bodies.has(node)):
_body_entered(node)
# check for exited objects
for node in intersecting_bodies:
if(!new_intersecting_bodies.has(node)):
_body_exited(node)
intersecting_bodies=new_intersecting_bodies
func _draw():
if(get_tree().debug_collisions_hint):
draw_set_transform(to_local(item.global_position + SHAPE_OFFSET), 0, Vector2.ONE)
intersect_shape.draw(get_canvas_item(), Color(1, 1, 1, 0.5))



I remember an issue about areas not detecting bodies when they were moved. However, I have been unable to find it.
We can use
force_update_transformon the objects that moved (the body and the area). But - sadly - there isn't an equivalent toforce_raycast_updatefor the area.So, I'll go ahead and give you the solution without area.
We will work on your holder script, because there is where you want to use the area...
For ease of use, I'll say have these exports:
Then, in
_physics_processyou aPhysics2DDirectSpaceStatelike this:Then you need to create a
Physics2DShapeQueryParameterslike this:Addendum: I realize that you have the area offset from the holder, so you might want to compute an offset transformation for that. On a similar note, I remind you that the exported variables are for ease of use, but you can define those values in code if that makes more sense to you.
And then we can query what bodies are overlapping the shape:
We can figure out what entered and what left... For that we need to add a variable on top (outside of
_physics_process) to keep track of the overlapping bodies:And now, in
_physics_processwe can do this:Be aware that since you wouldn't be using area anymore, it would not show up in the editor, nor while debugging with Visible Collision Shapes enabled. Thus, you need to use
_drawto have some representation of it. Be aware thatShape2Dhas adrawmethod that you can use for this:Addendum: Since you might want to draw the shape offset, you might want to use
draw_set_transform.And, of course, remember to call
update.