I’m building a Super Mario Land-esque game.
I have a Player, with an Area2D at the feet and an enemy with an Area2D at the head/body.
When I’m using the area_entered signal, I do get the collision, but never when I think the collision should happen, but when the player already touched the ground. So I have no way of knowing whether the player actually jumped ON the head.
After reading this post about Area collisions, I tried increasing the sizes of the areas, most notably the feet, to not only encompass the actual feet, but extend below the feet for 2 pixels.
That seemed to be enough to actually trigger the collision while the player is still in the air.
BUT now I’m wondering how consistent this behaviour is. Does this only work on my machine currently? Will this work for every possible way these areas are colliding? Or will I get a collision report in some rare case when the player already touched the ground?
I have used RayCast2D’s, but one isn’t enough there, if I want the whole area of the player’s feet to be able to collide with the whole surface area of the enemy’s head. I’d need multiple RayCasts then, depending on how wide the surface area is, to also have consistent behaviour there.
If this is the way currently, then so be it, but maybe there’s a better way I’m currently not aware of.
Use an Area2D with a CollisionShape2D below the player’s feet. Make sure the Area2D’s Collision Mask is only set to detect enemies and nothing else (say 3) and nothing on the Collision Layer is set.
Use a CharacterBody2D for the enemy with a CollisionShape2D that covers the entire body. Make sure the CharacterBody2D has the same Collision Layer set for enemies (again assuming 3 - but it can be whatever)
Use the body_entered signal of the Area2D to check for the collision.
Whenever your character’s Area2D overlaps with an enemy, it will trigger, and you can use the body variable to get direct access to the enemy.
Likely you are getting a collision report when the player touched the ground because your enemy’s Area2D’s CollisionShape2D was smaller than your enemy’s Characterbody2D’s CollisionShape2D - which it was colliding with, but you weren’t checking for that, and you were somehow colliding with the Area2D on the side when you hit the ground, or were colliding with the ground itself.
Collision Masks and Layers are set up properly and not unintentionally colliding with the ground.
I check the collision from the Enemy’s Area area_entered signal. The Enemy’s Area is larger than the CharacterBody’s CollisionShape.
Still when the Player’s Feet Area2D is too small, I only ever get a report when the player is already on the ground, in the IdleState and has no velocity anymore.
Making the feet shape’s size bigger in the y direction down produces at least a collision report where the player is still in the air and I can check for the player’s properties then.
But I’m still wondering if that is all that consistent?
What you are proposing sounds more like a “here’s how you do it properly, because what you did was wrong”. But what I did isn’t wrong, it was all set up correctly and still not getting me the results I expected. That’s why I’m assuming there could be a “better” way of doing that.
I cannot assume you have knowledge about things you didn’t talk about in your initial post. I was trying to give a full response that I hoped would work for you. I was also trying to make sure that anyone reading this post in the future because Google brought them here after a similar issue, would have a full response that would help them. Because I know how frustrating it is to be googling for answers and only get a partial fix to my problem.
I explained the way Godot recommends doing physics collisions. Which is not using two Area2D’s. It’s using one Area2D and a physical body. Area2D collisions are not as exact, and your problem is likely to persist if you continue to use two Area2Ds. I wish I could point you to documentation that explains this, but I couldn’t find it when I looked yesterday. Maybe this has changed since I read it sometime in the past 3 years and your solution is fine.
This seems to be the expected behavior. It might help if you changed the color of your other CollisionShape2D to red. Then anything that is purple is not going to trigger because to it covered by the first CollisionLayer2D.
I don’t know if you’ve read up on Hurtboxes and Hitboxes. If not, this video might help:
Thanks for trying to help!
I think I haven’t explained all that well what I’m asking.
It’s using one Area2D and a physical body.
I’ve tried that before and tried that now again, just to check. But it’s getting me the exact same result (with increasing the collision shape of the enemy’s body). When I reduce the collision shape y-size of the feet, then I get velocity=0 and with just one pixel more, I seemingly always get a velocity from which I can infer that the player is coming from above.
So it’s really just the speed of the collision checks that manage to report the collision in time, when I just add a few pixels more to the shape’s sizes.
But what about higher speeds when colliding? How do I know how big a collision shape needs to be to always guarantee that the collision happens?
The link that I posted above says that people use RayCasts to have collisions further along the line, but then I need multiple Raycasts and those maybe also need to be of a minimum length to report correctly.
So maybe there is no sure-fire way of getting collisions to always report correctly, when the velocity of one of the colliding objects is too big.
But then again
How do I know how big a collision shape needs to be to always guarantee that the collision happens?
Thanks, but that doesn’t really help and playing around with the size is what I already did to test the felt inconsistencies. Hence why I noticed that bigger = “earlier” collision.
I wouldn’t say that it’s weird. Did you read the post I linked?
CollisionShapes clipping through others with high enough speed also is a thing in many other games, so by now I’d say what I’m experiencing is quite normal.
I guess with all the information I gathered on this topic by now, the answer to the question how to always guarantee the collision at the right point in time is that you don’t and adjusting the size of the shapes until stuff hits when you need it, is the answer.
That does mean though that it’s highly specific per game, because higher velocities = bigger shapes necessary. As the post I linked also already explains.
I did not read that post before. I did now. Based on that, if you know your velocity in pixels/second you can calculate how many pixels deep your Area2D needs to be. You just divide your pixels/sec speed by 60. As long as you have an Area2D at least that many pixels deep (rounding up to the nearest whole number) you should always geta collision detection. If you change that speed, you can always recalculate the size of your Area2D on the fly.
NOTE: This is based on the default settings for physics frame processing. If you change it, your math would also have to change.
So that means for me, if I want consistent behavior, I at least have to add a maximum velocity that the player can reach while falling, so I don’t get clipping in some unforseen heights the player may reach. Then I can use the maximum velocity as a base to calculate the minimum size for the collision shapes.