1
\$\begingroup\$

I'm scripting my own collision logic for a 2D game that works like this:

  1. Boxcast in the direction of movement against appropriate colliders in the scene
  2. If a contact is detected, move to the RaycastHit2D.centroid
  3. Move back in the opposite direction of movement while trying to maintain constant "padding" around level geometry
  4. Finish movement (using something similar to a collide and slide algorithm)

My issue is with #3. Once it's time to resolve collisions, instead of resolving in the direction of the surface's normal, I want my collider to be moved backwards in the opposite direction from which it just came (easy enough). But I also want it to be placed in a such a way that it is displaced from the contacted surface by the surface's normal multiplied by some padding amount.

Let me try to clarify with these pictures:

Here, my collider in green boxcasts (in red) against the square shape; the translucent, dark box around it represents my desired padding around the geometry. The collision is then resolved in the direction of the red vector. This is simple and works fine because the surface normal is identical to my desired resolution direction.

enter image description here

But then if the collision occurs on rotated geometry, or I contact, for example, a 90-degree surface while moving diagonally, I don't know how to find the appropriate resolution vector, as the opposite direction of my movement is different than the surface normal (in white).

enter image description here

My goal is to find a reliable way to calculate the red vectors regardless of the contacted surface's normal, or to find a different way to maintain a constant distance around my collision geometry. I have found this problematic in certain scenarios, especially in top-down games in which the player may move in several directions on the same surface.

\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

This is a right triangle.

enter image description here

You can get the angle A in degrees by getting the angle between a horizontal vector and the normal.

And then you get the red vector length by doing:

cos A = adjacent leg / hypotenuse.

You already know the white vector length (half the box + padding), which is the adjacent leg. Now you can solve the hypotenuse and that is the length of the horizontal red vector.

\$\endgroup\$
3
  • 1
    \$\begingroup\$ This is a nice solution; thanks. I would be curious if it's possible to do this just using vectors, though, instead of with trigonometry. \$\endgroup\$ Commented Feb 7, 2022 at 1:02
  • \$\begingroup\$ I suppose you could get the location of the point at the tip of the white vector (let's call it 'p1'), then you get the difference in height between p1 and the center of the box and create an up vector with that length, then project that vector on the vector that is perpendicular to the normal, then add that vector to p1, and you'll get the point at the tip of the red vector (let's call it p2). I guess that's what you need to find, but if you need the length of the red vector just get the distance between p2 and the center of the box. \$\endgroup\$ Commented Feb 7, 2022 at 1:13
  • \$\begingroup\$ I realized this only works if the center of the box is at the same height as the contact point. But you can just replace the center of the box with the contact point in the answer (and the white vector length will just be the padding size) and I think it'd work too. \$\endgroup\$ Commented Feb 7, 2022 at 1:21

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .