Is it normal that body_enter_shape() and body_exit_shape() callbacks keep beeing called?

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By cardoso
:warning: Old Version Published before Godot 3 was released.

I have the following nodes:

...
KinematicBody2D
   shape1
   shape2
  ...
Node2D
   Area2D
       shape
   StaticBody2D
       shape
  ...

body_enter_shape() and body_exit_shape() signals are used to detect which one of the KinematicBody2D shapes is ‘touching’/entering the Area2D shape.

The Area2D shape is not big enough to completly overlap any of the KinematicBody2D shapes (though I tested case where Area2D was big enough for that, results were the same).
And all of the shapes are rectangles.

I put a print in both the signal callbacks to check when they get called.

The issue is that when the KinematicBody2D is touching the Area2D - whether or not the KinematicBody2D is stopped - both the callbacks are being called forever (first the enter signal callback and then the exit one). Like every second, or something like that.

Is this behaviour normal?

There is a StaticBody2D next to your Area2D, are they overlapping? How are they built? Are they on the same layers?
Also, are shapes made like rectangles or actually are RectangleShapes?

I tried to reproduce it but things work properly on my end, thought my Area2D also detected the StaticBody2D.

Zylann | 2017-05-13 01:15

I think I solved it, I’ll make a reply to my question!

Thanks for helping, I followed your line of logic (using another body I created), and everyhing was working well.
In the end it was a problem with shape extents being changed.

cardoso | 2017-05-13 12:36

:bust_in_silhouette: Reply From: cardoso

Loos like I solved the issue! It was a problem with an AnimationPlayer setting shape extents to default values.
Even though the values being set were the same when player was idle or moving, it still caused the signal callbacks to be called.
Chaging the shape node position creates no problems. Just changing the extents.

Please note that you should not touch anything in CollisionShapes at runtime, they are likely to not do what you expect, and they just won’t work at export because they get stripped out. They only exist as editor-only helpers, so that shapes can be drawn and positionned easily in the editor. Countless people made the same mistake ^^"

To change shape extents using an animation or tween, you should make a custom property that sets the shape’s property using the shape API on nodes that inherit CollisionObject2D: CollisionObject2D — Godot Engine (stable) documentation in English

Also I don’t know how well the physics engine supports shape resizing at runtime. You said it works fine but I think it doesn’t do what you think due to what I said above. Not many physics engines react well to shapes changing every frame^^

Zylann | 2017-05-13 14:25

I am not using anymore shape extents modification in animations.

But I still have the position of the node holding the shape (“editor-only helper”) being changed in an animation. So it is not recommended?

I do that to check if an attack shape ‘hits’ an enemy body shape.
I then check for ‘collision’ like this:

player.shape_attack.get_shape().collide(
		player.shape_attack.get_global_transform(), 
		enemy.shape_body.get_shape(), 
		enemy.shape_body.get_global_transform()
	)

(I guess I could also use signals here to detect if the shapes ‘collided’)

Thanks for the help!

cardoso | 2017-05-13 15:25

You should not script them or access them either. Try to export your game to see what I mean^^

Zylann | 2017-05-13 15:44

I exported for windows. The ‘collision’ check seems to be working well (player attack shape ‘hitting’ the enemy body shape). But…

So just to be sure, get_node("shape").get_global_pos() is unreliable?
And get_node("shape") is only usefull in the code to get a shape ( get_node("shape").get_shape() )?
And using the track ../shape:transform/pos in an animation is also unreliable?

So how can I move the position of an actual shape to match or be similar to a sprite animation?

I see there is a collide_with_motion() in the Shape2D API. Could that be of help in this case?

This is a bit confusing topic.
Thanks for the help!


Edit:
i found this: Collision shape cannot be used as a track in the animation editor / Collision shape cannot be used as a track in the animation editor · Issue #1045 · godotengine/godot · GitHub
Where looks like they “kind of improved” this:

It’s still not a replacement for not using the internal shapes of
CollisionObject, that will have to happen in
3.0, due to requiring to break compatibility… But for practical uses this should be enough I hope.

But I m not sure it it is exacly what we are talking about. Also I did not totally undertand if it is written that in 3.0 the shape editor helper would be reliable or that for sure we would need to use “the internal shapes of CollisionObject”.

cardoso | 2017-05-13 16:29