I have a KinematicBody2D player object and some StaticBody2D platform objects. If the player collides with an object with a normal within an angular range that I've designated as the floor, I want the player to adjust its rotation to match the angle of the floor and snap down (i.e. rotate about the corner that contacts the surface). This is fine until we encounter a situation in which the player contacts the sloped floor at a position where the floor intersects another platform that's at a different angle, since rotating and snapping down would cause us to intersect and jitter between the two floors.

My proposed solution was to rotate and snap, and then check if we're intersecting any platforms. If we aren't intersecting, we're fine and can move on, but if we are intersecting, then undo the rotation and snap, and try again with a smaller angle a few times to find a close approximation to the angle that rests the KinematicBody2D's CollisionShape2D on top of both platforms, at the angle of the line between the collision points (see image below).

My problem lies in the ability to check if our rotation would cause an overlap. If using `test_move` with a `rel_vec` argument of Vector2(0,0), we still detect a collision even when just sitting on a single floor, I guess since the objects are touching (I measured to ensure my math was correct, and the player rests perfectly on the floor).

My next thought was to try attaching an Area2D to the kinematic body with the same CollisionShape2D as the one I attached to the kinematic body, and then call `get_overlapping_bodies` on it, but if I'm interpreting the results correctly, it doesn't count the new overlapping platforms until the next physics process. I also can't just use an Area2D's overlapping signals, since I need to be able to reverse the rotate and snap mid-process to try a different one.

Does anyone have advice on how to best proceed? Thanks!

in Engine
edited

I ended up solving this using a space state check. This is probably horribly inefficient, but didn't give me any lag at my current project scale. If I run into issues later and manage to find a better solution, I'll return to this post. Using the same methodology I described in the question, I would rotate about the corner we land on, and check my collision using the following code:

``````space_state = get_world_2d().direct_space_state
params = Physics2DShapeQueryParameters.new()
params.set_shape(hitbox.shape)
params.collision_layer = 2
params.transform = hitbox.global_transform
params.collide_with_bodies = true
collision_result = space_state.intersect_shape(params)

# If this rotation would put us in collision, undo and step
if collision_result.size() > 0:
``````

If the check at the end succeeds, we undo the rotation, and try a rotation at a smaller angle for a few iterations, until we exceed max iterations (I'm using six), only undoing a rotation if we have a collision (so if we don't collide, keep that rotation and then add onto it).

by (84 points)