0
\$\begingroup\$

I am working on a 2D platformer in Unity and am doing my own collision detection.

I was previously using the method described in Sebastian Lague's popular YouTube tutorial, where you break your velocity into its horizontal and vertical components, then cast a series of rays horizontally and vertically from some skin_distance within the characters bounding box, checking for collisions. The length of the raycasts is the length of the velocity component plus the skin_distance. If any of the rays collide, you curtail the ray length and continue to iterate through the remaining arrays, until you're out of arrays, at which point you set the velocity to your final ray length (minus skin_distance).

This method works well enough, and Sebastian's tutorials even extend the method to solid slopes.

I want one-way slopes, however. One-way slopes are slopes that you can jump up through from underneath to land on them from above.

I've been at it for a week now, and I can't seem to extend Sebastian's method to work for them.

I've tried several things. First, I've represented the slopes & my flat one-way platforms as line segments using EdgeCollider2Ds. Then, I created methods for OneWayHorizontalCollisionDetection() and OneWayVerticalCollisionDetection(). The former checks if a velocity-lengthed horizontal ray from the bottomleft or bottomright point of the character's bounding_box intersects a slope. If it does, x-vel and y-vel are adjusted to snap the character onto the slope and move the character up the slope.

In the latter, for jumping up through the slope, if my character is ever moving down and one of its vertical rays hits the slope, I check to make sure the correct bottom corner point is also above the slope. If it is, then I'd curtail the velocity so the character landed on the slope properly (see diagram below).

No matter how much I try to massage things, however, I always encounter an issue. Part of the problem with this method, I think, concerns an asymmetry with vertical detection versus horizontal detection.

Consider the below diagram. When doing vertical collision detection, if my character is falling and the green point in the bottom right corner is above the slope, and the ray intersects, I'll move the char down so that green point is flush with the slope. The character sits nicely on the slope and everything seems fine.

enter image description here

If I then press right to start moving up the slope, my horizontal collision detection will see the slope on the right, and snap the green point on the right side of the character to the slope. The character will then move up the slope just fine. If I then stop moving, however, because the bottom green point is now below the slope, the character will fall through the slope.

Even trying to massage my way around this problem, I've encountered a whole host of other issues, particularly at the point of transition from the slope to the flat platform at the top. Issues with floating point imprecision interfering with is point.y >= point2.y complicated matters even more.

I've come to think this "skin distance raycast" method is not the correct way to proceed if I want one-way slopes. I am simply running into too many issues.

I tried converting my system to use boxcasts of my character's BoxCollider2D, but it didn't pan out.

Then, I tried to move back to raycasts, but I tried casting them at the true corners of my bounding_box, rather than some skin width inside. I didn't make much progress there either, though my gut tells me using true corners is going to be the most elegant way to implement one-way slopes. At least using true corners, you know exactly which point you want to be snug on the slope.

So, my question is, what is a viable collision detection paradigm for one-way slopes? Could anyone sketch for me what an implementation of one-way slopes would looks like?

I know there's dozens of questions about slope collision detection, but I have yet to find a single one which specifically mentions one-way slopes (which seems to be a harder problem).

NOTE: I am open to both solutions that put the bounding box bottom corner on the slope, as well as those that put the bounding box's midbottom point on the slope, though I would prefer the former. I am only trying to accommodate 22.5-degree slopes.

\$\endgroup\$
3
  • \$\begingroup\$ You need to get this working with just one point: The one at bottom centre of the sprite. Once that's working, make a copy / commit to version control, then take it from there, if you want to do more. \$\endgroup\$ – Engineer Jan 18 at 6:31
  • \$\begingroup\$ How about detecting slope by making 3 raycast, two on the bottom of the edges, and one in the bottom center. Then, if there's a big difference between the middle raycast and one of the edges in term of distance, you can tell that there's a slope ? \$\endgroup\$ – Takah Jan 18 at 10:45
  • \$\begingroup\$ testtestesttest \$\endgroup\$ – GrimGrom Feb 26 at 23:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.