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

Collision result prioritizes nearest point rather than the length of the collided size #46746

Open
Tracked by #45334
hydescarf opened this issue Mar 7, 2021 · 4 comments

Comments

@hydescarf
Copy link

hydescarf commented Mar 7, 2021

Godot version:
3.2.3

OS/device including version:
Windows 10

Issue description:
I believe this isn't technically a bug, and it's intended. When the collider collides, it finds the nearest place to get off the collided object.
However, in my case, I have a code where the player RayCast2D can summon an object (on the arrowhead). If the summoned object is bounded to touch a wall, it should bounced behind the wall.
This is what I expected to have:
image
Straight vertical line on the left as wall, rectangle box as summoned object, and arrow as player.

Instead, the summoned object bounced below the wall's end point (I used SegmentLine2D but it also happens in RectangleShape2D).
Doesn't matter if I used move_and_collide(), or move_and_slide(velocity, Vector2(1,0)).
image

On the other hand, if the collider size is smaller than maybe, the wall length?, it bounced back normally
image

or if the wall length is longer and the collider is around the center point, it also bounced back normally.
image
In this case, I was wondering, is the collision depending on the center point instead of overall shape? Because it will still happen if you summon the collider around the bottom of the wall regardless of the wall length.
image

My question is:
Should the collision result be based on the length of the collided surface instead of the nearest end point? This one is especially crucial for line-based CollisionShape like SegmentLine2D, because we don't need that at all, but only the length between two points.

Minimal reproduction project:
bug report.zip
Note that in the file, there is a Raycast2D to determine the summoning point, when it touches the wall, the to-be-summoned object will automatically bounce back, that works well and it's not related.

@pouleyKetchoupp
Copy link
Contributor

In a scenario like this where the kinematic body starts stuck inside another shape, it gets unstuck by finding the shortest path to be pushed out, so that's the expected behavior with a short segment shape and a long object.

Could you describe a bit more in context what you're trying to achieve in your game? That might help finding the right workaround (or bug to fix).

One way to solve this problem could be to use LineShape2D instead of SegmentShape2D, because in this case the rectangle would be only pushed along the width of the line. But that works only if you can use infinite lines in your case.

@hydescarf
Copy link
Author

hydescarf commented Mar 10, 2021

Thank you for trying to help out! But I have already made a workaround behind this.
For Local (summon.script): adjust the length of RayCast2D with the inclusion of summoned object size.
For Global (general collision detection): manually recalculate the position difference.

I didn't consider LineShape2D as I had trouble using it, and heard it was not recommended due to performance issue. And yeah, it's not what I wanted as it's an infinite line.

Also, yes, I also understand the logic behind this. The reason I post this was because I'm curious if this can be considered an enhancement to line-based collisions.
I'm having a custom collision shape where I used SegmentShape2d for all platforms and walls. Would have considered PolygonShape2D but the ending gap cannot be unclosed and it looked confusing in the editor, its collision detection is also unstable.

On line-based collision shape, its surface should be prioritized than its starting and ending points. Everything's working great if they were moving and then touched the shape, but not if they were to suddenly appear onto the shape. But when they do, I expected them to find the nearest surface instead of point.
I thought the method move_and_slide(velocity, vector.RIGHT) would work, but it doesn't. I tried the following where I summon an object onto the arrowhead with vector.UP, it fixed its position to the ending point instead.
image
Considering that SegmentShape2D has almost no size, and its position.x is parallel to summoned object's position.x, they should focus on position.y instead.

There's not much usage for points in line-based shape other than setting up the position, and it should not be considered as a floor/wall. Nearest path should be "above or below the lines between two points". At this point, no object could land above a vertically straight line shape.

Though, with my logic, then there's this issue I don't know which to prioritize:
image
It's a composite of two SegmentShape2D.

So, my view could be narrow and flawed, would be nice if I can get an explanation why this doesn't work.

Edit: I confused myself a bit, but that crossed texts should only occur when they appear suddenly, not when they moved and touched it.

@pouleyKetchoupp
Copy link
Contributor

@hydescarf Sorry for the delayed answer. It's nice to know you already have some workarounds!

I think this use case makes sense, it's just not easy to make it work in a generic collision algorithm. And in a different scenario, someone might need segments to push objects from their ending points.

I can see how it could be useful to use segments this way though, and possibly polygon shapes as well. Maybe there could be an option for segments or a separate shape that would push objects only along their normal like a line does. That would require some more investigation to figure out how to implement it and a proper proposal from me or another contributor.

In the meantime the best option is to use a custom logic in script like you did in your workarounds.

@hydescarf
Copy link
Author

hydescarf commented Mar 16, 2021

Yeah, I figured as much.
I don't doubt the possibility of people using the points for collision, but I'm just not sure what case would it be.

I think there's two ways of making this works,

  1. Make move_and_slide(vector2, DIRECTION) relates to the line (or collision in general), this way the point collision would still function, but the priority of nearest path sets on the direction.
    As for my issue, since in the description for direction, it says it would detect floor and wall automatically, then maybe my issue can be fixed as it would also detect the wall and bounce that back at the surface instead?
    The condition to separate this from existing path finding is part of the object size might have to be outside of the collision floor/wall, and then determine the length of the non-overlapped size and set the nearest path based on it.
    I feel like there's a flaw in this suggestion 🤔
  2. Make something similar to one-way-collision.

Thank you for your feedback. In any case, I'll continue using my workaround for now since my collision is somewhat half-customized anyway. (Using Line2D to simulate PolylineCollision :p)

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

No branches or pull requests

4 participants