Godot: check overlapping with is_overlapping() function for PhysicsBodies

Created on 20 Dec 2017  Â·  17Comments  Â·  Source: godotengine/godot

In order to check if something is overlapping with something without colliding with it is by using an Area node where this area checks if a body/area enters this area. This is fine for stuff like doors or special areas where it triggers something.

But when using a KinematicBody for a character, sometimes you want to check if it’s overlapping with another body without colliding with it. For example in a side-scroller game, you have an enemy and a player, both KinematicBodies where they collide with the surroundings, when the enemy charges to the player, in order to cause him damage, they need to touch, but this enemy should pass through him without colliding with him but colliding with the rest world, this would trigger a knockback on the player.

But this can’t be done because they need to be in the same collision layer/mask and collide in order to exist for each other.

So, what I suggest? A new function called Is_overlapping() with a sort of get_overlapper() function so you can get the body that’s overlapping with. Same as is_colliding() and get_collider() functions:

if (Is_overlapping()): 
    var body = get_overlapper()
    if body.is_in_group("player"):
        body.damage( -1 ):

Still, this won’t work on the current collision system because they will always collide unless you disable the shape or change the collision layer/mask, but that makes the body “inexistent” for the other bodies.

The only way for this to work is by changing how the collision system works, letting the developer to set if it collide or not with certain layers or to check overlapping instead (check #14883 ). Overlap check can work only when the collision is not set to true, this part its hard to figure out what do you think?

archived discussion enhancement physics

Most helpful comment

Area node have a method called get_overlapping_bodies() and get_overlapping_areas().
I belive that you can achive what you need by adding an area for the player and set this area at the inspector Monitoring off and Monitorable on. On the enemy again you can add an area with monitoring on and monitorable on or off ( it doesn't matters).
Other from that set the stage collision to two layers 0 and 1 for example and set the player to interact with 0 and the enemy with 1.

All 17 comments

Area node have a method called get_overlapping_bodies() and get_overlapping_areas().
I belive that you can achive what you need by adding an area for the player and set this area at the inspector Monitoring off and Monitorable on. On the enemy again you can add an area with monitoring on and monitorable on or off ( it doesn't matters).
Other from that set the stage collision to two layers 0 and 1 for example and set the player to interact with 0 and the enemy with 1.

KinematicBody will never overlap with another body because every frame separates itself from everything else. You will have more luck checking the list of collisions found in move_and_collider or move_and_slide

@kakoeimon yes I know, I was going to point that out but the post would be longer, now you don´t think that's too much for something that simple? also you would have to add an exception on the player body or put the area or the player in a different layer so the area doesn't check the player overlapping all the time.

@reduz sorry, I didn't got that

@aaronmzn You do not have to add any exception at all, just put them on different layer, plus those are areas, you can use the methods and the events made for areas only. e.g. get_overlapping_areas() or connect the area_enter.

I just want to say something more general here about Godot.
Godot is not an engine which was created by crazy ideas of Reduz and Punto, but it is based on well known techniques and you can find many technical papers implemented inside the source.
With that said it is better to try to find out how things work in Godot, than trying to find alternative ideas to ask for implementation. I am not trying to be rude over here but I believe that you will benefit by learning the techniques already implemented.

Plus if you get a book about how to create a game engine or physics engine or etc. you will see that many of those things are inside Godot.

For example the physics engine Godot is very similar to Bullet cause those two engines used well known techniques and tested ideas.

@kakoeimon Would't be get_overlapping_bodies() instead? that would return all the bodies that are inside the area, I already did this with a melee weapon as an area2d inside the player where I needed to have its own body shape so I can change its size and position to adapt it to the sprite frame using AnimationPlayer and a function trigger that disables then enables monitoring in the area for each frame I want to cause damage (but if the animation is too fast sometimes it wont register it, bummer)

but if I want to use the same body shape, I can't, I need to give this area a body in order to make it work, if I want to have exact body shape and position than the main character has, I will need to put it above and adjust it exactly like the main body shape. the only thing the body will do is to check overlapping since it already has a BodyShape, that's it. But the current system won't let that happen because as long as you set another body mask to the body you want it to check, it will always collide. Unless there is a way you can decide if you want it to collide even if you set the collision mask, this way it can check overlapping only if they are in the same/mask and it won't collide unless you tell them to.

Don't worry, you're not being rude, I understand it's based on tecniques that where already tested, and I'm not trying to say it's not well done. I'm just checking if it's posible, since it's something simple, but I guess that would need changes in the current collision system.

@aaronmzn I realy cannot understand what you are trying to achieve, your explanation is confusing to me.
In the melee weapon you said, I believe that it is better to use Signals, to check if a "body_entered" the area for example. As for the speed you have several options. For example you may make it just slower (the obvious solution), the other is to make the area wider or make the area wider when the animation is fast and last just do not move the area at all and place it where it is supposed to hit and enable it for 2 or 3 frames todetect the bodies or areas that entered. Keep in mind that when you enable an area will trigger the signal "body_entered" for all the overllaping objects.
In the next paragraph I do not understand what you are trying to say sorry.

@kakoeimon I'm not moving the area, yes I'm using body enter signal, I'm moving the body shape inside the area not the area itself.

And on the other paragraph I'm saying I want to use the player's exact body shape to detect overlapping, but for that I have to use an area inside this body and then copy the size and position from the main body shape to the area's body shape, that would be kinda awkward with the bodies above of each other, and then I'm saying to solve this I'm suggesting a function check overlaping and get the overlapping body for the the physicsbodies, and wouldn't be necessary to add another body with a body shape inside the main body.

But I think the only way of that to happen it's if while setting the character to collide with something, instead of straight up colliding with it, you can tell the body if it should collide with this mask or instead would be able to detect overlapping, if you set collisions to true then checking overlapping can't be done.

@reduz
I know this discussion has been quiet for over a year but I decided to put my input here instead of opening a new issue. I am currently designing a 2d game that is using multiple Area2D for custom application of friction. In order to apply apply the friction, the areas use get_overlapping_bodies() to find all the bodies they need to apply friction to. The problem I am currently working to solve is when a body overlaps multiple areas as each area applies their friction to the body, which is incorrect. Personally I think it would be better if PhysicsBody2D had a comparable function, get_overlapping_areas(). This would allow the body to find all the areas and make the decision of which friction to apply or even to average the frictions. While there are workarounds, like creating an array in the body and having the areas fill the array with their friction vectors, I still think having a get_overlapping_areas() in PhysicsBody2D would be a more natural solution.

Having a get_overlapping_areas() function (or signal) available to the RigidBody node would be really useful for things I would like to accomplish.

Hi @Diaspater, you rightly think that this seems more natural, but it is natural from the logic side and not from the code base side.
I am saying this cause, the rigidbody does not make a collision check against an area.
This means that in the end you are asking for the extra functionality of the solution (create an area in the rigidbody) to be included in the rigidbody.
This is going to to slow down the entire physics engine.
Also, if we are going to consider that we do not want to bloat the engine with extra functionality which can be resolved with little bit of code, the idea of having this functionality as optional, must be abandoned too.

@Diaspater I have no answer on your question, but let my evaluate little bit more on the previous conversation.
What I am saying is not from studying Godot's source code but from experience of using several physics engines. Physics Engines are all almost identical, for example the old 3d physics engine of Godot was similar to Bullet Physics, the 2d physics engine is similar to Box2d.
The real dif of those engines are the joints and the character modules, but the base remains the same.
I have read some books and articles about physics engines( which I never achieved to implement, I am not a good coder). This is the reason I am saying what I am saying.

For example in Box2D you set a fixture (think about it as something between rigidbody and collisionshape2d) to a sensor, this will turn it to a fixture that will not have a collision response. In Godot 2 if I remember correctly we had this option, now in 3 we do not, but it is similar of having an Area under a RigidBody. It is the same thing.

The keywords in all this is "collision response". In Box2d you turn a fixture to a sensor, in Godot you use Areas. Collision detections are really fast, what may be considered slow is the collision response cause it will have to calculate the reaction and make several more collision responses in the process of emulating the response.

CollisionShapes can be shared between PhysicsBodies for example you can have a copy of the CollisionShape inside the RigidBody inside the Area you want for detection. Under the hood those CollisionShapes are the same. This mean that those shapes share the changes you may make.

For example try this.
Create a RigidBody2D, inside it create a CollisionShape2D, then create an Area2D inside the RigidBody2D, duplicate the CollisionShape2D (ctrl + d) drug one of those two CollisionShapes inside the Area2D.
Try now to change the size (by using those red marks) of the CollisionShape under the RigidBody and you will see that the changes are passed and to the CollisionShape2D under the Area2D.

I am writing all this to show to you that the solution of having an Area2D under a RigidBody2D is not just a solution, but it is the right solution.

I accidentally deleted my question that you second response was in response to so I am just reposting it for clarity.

@kakoeimon Ty for your explanation. That being said, currently I am using Physics2DDirectSpaceState.intersect_point( ) in a RigidBody2D to work around this limitation. I haven't had much luck tracking down the specifics of this method in the source code. I am wondering if constantly polling this with a moderate to significant but limited number of entities is a bad idea from a coding point of view and if it is, if you could point me in the direction of a better method.

@kakoeimon In response to your second response, ty again for that explanation. I initially thought what you were describing didn't work so I am going to explain why so anyone else reading this having the same issue might know why. When I first starting working with Godot a few years ago I originally used a Games from Scratch guide to familiarize myself with it. Being from 2015, its understandable that not everything it described is still accurate.

In the physics part, https://www.gamefromscratch.com/post/2015/03/19/Godot-Engine-Tutorial-Part-7-Physics-and-Collision-Detection.aspx it says that CollisionShape2D and CollisionPolygon2D are exactly the same except with CollisionPolygon2D you can define your own shape. In Godot's current form this is not true any more, at least from the editor's perspective. However that line stuck in my head and I was trying to duplicate a CollisionPolygon2D which does not have a shape resource like CollisionShape2D does and therefore the shapes are not linked.

Using Godot 3.1-beta.1 i did run into one minor issue. When using a CollisionShape2D and creating a ConvexPolygonShape2D, it does not let me create the polygon shape by clicking directly on the pixel grid like when I was using a CollisionPolygon2D. I instead had to inspect the shape in the Inspector tab and manually enter the vectors for each of the points.

One concern I have is from the documentation on CollisionShape2d, https://docs.godotengine.org/en/latest/classes/class_collisionshape2d.html it seems as if the shapes are only linked in the editor meaning that if I change the shape of the PhysicsBody2D at runtime, I also need to make sure to change the shape of the CollisionShape2D as well.

As far as the functionality of having an Area2D under a PhysicsBody2D for detection, that is working exactly as I wanted with the only annoyance being that I have to then pass the detection results to the body for processing.

@Diaspater He is (almost) right that CollisionsShape2D and CollisionPolygon2D are the same thing (I may add, almost the same thing). CollisionPolygon2D just gives you the tools to draw your polygon.
The point here is that physics engines are using the "Separation Axis Theorem" for collision detection, the limitations are that this technique can handle only convex polygons. If you want a concave polygon then you have to create one by placing several convex polygons at the right place. CollisionPolygon2D is, in the end a tool that will create those convex polygons in place to "mimic" the concave polygon.
When you make a change on the CollisionPolygon2D, Godot will destroy the previous convex polygons and will create new convex polygons.
Probably this is the reason the changes of the CollisionPolygon2D are not passed to the duplicate.
Also keep in mind that you have to create the shape in CollisionShape2D before the duplication to share the shape.

The "annoyance" of having to "pass the detection results to the body for processing." exists cause you do not treat the Scene Root as an extension, as a new thing.
What I mean is, that you do not have to pass the results, but you have to keep reference of your Area2D (e.g. : onready var area = $Area2D) and use the functions of the area when ever you need them in the script of the Scene Root of your object. This way you do not pass anything you just use the functionality of the parts (Nodes) of your creation.

I actually was just wondering why only area2D has get_overlapping_bodies() and get_overlapping_areas()

physics bodies like kinematic static, and rigid don't always have to collide with each other.
for example you might want the player to collide with a wall but not an enemy
and then you might want to check if that enemy is actually overlapping a wall.

using collisions masks and this function in physical bodies you could do this.

I think this feature could be useful for checking if a player is stuck in a wall for instance. At the end of movement for example, if the player's script could check get_overlapping_bodies() and it was in fact stuck between a moving platform and the ground you could use this to kill the player.

Of course there are other solutions for this, right now I'm just using an area 2D that is strictly smaller than the collider and checking that get_overlapping_bodies() for the same effect. Sorry if this is too unrelated to post here?

Feature and improvement proposals for the Godot Engine are now being discussed and reviewed in a dedicated Godot Improvement Proposals (GIP) (godotengine/godot-proposals) issue tracker. The GIP tracker has a detailed issue template designed so that proposals include all the relevant information to start a productive discussion and help the community assess the validity of the proposal for the engine.

The main (godotengine/godot) tracker is now solely dedicated to bug reports and Pull Requests, enabling contributors to have a better focus on bug fixing work. Therefore, we are now closing all older feature proposals on the main issue tracker.

If you are interested in this feature proposal, please open a new proposal on the GIP tracker following the given issue template (after checking that it doesn't exist already). Be sure to reference this closed issue if it includes any relevant discussion (which you are also encouraged to summarize in the new proposal). Thanks in advance!

Was this page helpful?
0 / 5 - 0 ratings