Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RayCast2D and CollisionPolygon2D collisions are unreliable #38873

Closed
Tracked by #39876 ...
KoBeWi opened this issue May 19, 2020 · 5 comments · Fixed by #54857
Closed
Tracked by #39876 ...

RayCast2D and CollisionPolygon2D collisions are unreliable #38873

KoBeWi opened this issue May 19, 2020 · 5 comments · Fixed by #54857

Comments

@KoBeWi
Copy link
Member

KoBeWi commented May 19, 2020

Godot version:
3.2.1

Issue description:
The Sprite becomes red when the raycast's is_colliding() returns true.
3dTNWfTIq1
As you can see, raycast will detect collision only with the edge of polygon's quad and will fail inside.

Minimal reproduction project:
ReproductionProject.zip

EDIT:
Also tested with rectangle CollisionShape2D and it works correctly, so it's indeed a bug with polygons.

@bojidar-bg
Copy link
Contributor

bojidar-bg commented May 20, 2020

CollisionPolygon2D decomposes into multiple ConvexShape2D shapes when in "solids" mode:

if (solids) {
//here comes the sun, lalalala
//decompose concave into multiple convex polygons and add them
Vector<Vector<Vector2>> decomp = _decompose_in_convex();
for (int i = 0; i < decomp.size(); i++) {
Ref<ConvexPolygonShape2D> convex = memnew(ConvexPolygonShape2D);
convex->set_points(decomp[i]);
parent->shape_owner_add_shape(owner_id, convex);
}
} else {

To determine whether a shape intersects a raycast, CollisionSolver2DSW::solve_raycast uses Shape2DSW::intersects_segment:

if (!p_shape_B->intersect_segment(from, to, p, n)) {

Unfortunately, ConvexPolygonShape2DSW::intersect_segment does not check if both points are inside:

if (!Geometry::segment_intersects_segment_2d(p_begin, p_end, points[i].pos, points[(i + 1) % point_count].pos, &res)) {

Probably such a check could be done after failing to intersect any of the lines using Geometry::is_point_in_polygon. Given that is_point_in_polygon does the check using any point definitely outside of the polygon, maybe some part of it can be merged with the loop in intersect_segment. Maybe even doing something like further_away = get_aabb().position - Vector2(1, 1), as any point outside the AABB of the polygon is definitely outside the polygon.

Edit: there might be faster ways to check for this, e.g. see https://stackoverflow.com/questions/1119627/how-to-test-if-a-point-is-inside-of-a-convex-polygon-in-2d-integer-coordinates

@Calinou Calinou added this to the 4.0 milestone May 20, 2020
@Xrayez
Copy link
Contributor

Xrayez commented May 21, 2020

See also #38343, #35845.

@knightofiam
Copy link

Any workarounds?

@KoBeWi
Copy link
Member Author

KoBeWi commented Dec 16, 2020

@knightofiam Area2D or KinematicBody2D and test_move()

@Houkime
Copy link

Houkime commented Jul 11, 2021

Still valid for v4.0.dev.custom_build [a0d800e]
That could be said to be a perfomance feature, but then the mode probably should not be called a solid.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment