Small offset in collision normal

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By akhenaten
:warning: Old Version Published before Godot 3 was released.

Hello!

I’m writing a simple Breakout style game, and have encountered an odd issue. I am using my own code for the movement and bouncing of the ball, but I’m using Godot’s collision: the ball is a KinematicBody2D and CollisionShape2D, and the bricks are StaticBody2D’s and CollisionShape2D’s.

The collision/bounce code (written for the ball) looks something like this:

if (is_colliding()):
    var n = get_pos() - get_collision_pos()
    print('n = ', n)
    
    n = n.normalized()
    var a = moveVector.dot(n)
    var p = (2.0 * a)
    
    newMovement = moveVector - p * n

The issue I’m having is with n. When the ball deflects off a horizontal surface, the collision normal should be n = (0, 31), where 31 is the radius of the ball. Instead, I get results logged that look like this:

n = (-0.976074, 31.36499)
n = (-31.96582, 0.304688)
n = (-0.880859, -30.671875)
n = (-0.879395, 31.371582)
n = (-0.881592, -30.671631)
n = (-0.88147, 31.355103)
n = (-0.881836, -30.683838)
n = (-0.881165, 31.378418)

The x/y values are always offset just a bit, and the result is very bizarre bouncing physics. Is this just expected with Godot’s collision system, or am I missing something simple?

I worked around the problem with what amounts to if (x < 1): x = 0, y = 31 but I’d love to know why the problem is happening in the first place.

Thanks for any help!

:bust_in_silhouette: Reply From: Zylann

I assume you are doing this every frame, so first, make sure you are doing this in _fixed_process().

You have slight offsets because when collision is detected, the ball is already in collision. To be in collision, it has to overlap what it collides with (before resolution), so what you get is a position that is slightly inside the wall. What you expect (0,31) would be the resolved vector, not the one you detect, because you are using KinematicBody and you are expected to handle collision resolution yourself.

Also your results show that the bounce is not always towards a horizontal surface, looks like you also have vertical ones.
My guess is that your bricks are either not evenly placed (with pixel snap), or are not rectangular, which leads to tiny holes where collision detection can report unwanted results. Or is it actually the result of your issue?

I did a test myself and obtained the consistent result of (0, 31.011665). So as I explained, Y is slightly inside the wall. About X, your ball is probably not going straight up in the first place.

Thank you for the helpful answer! Yes, I think you are spot on with all of that. There were a couple of vertical surface bounces that I forgot to mention, when the ball hits the wall, so that was expected.

To be completely clear, if I wanted to remove this offset, I would need to detect the true point of collision using a method like in this often referenced article? Or use something other than KinematicBody.

Thanks again for the insight.

akhenaten | 2016-12-14 01:17

I’m not sure you really need to be that precise, getting the current speed of the ball and mirroring it along the normal should be fine. If you want a very good precision you could use raycasts to know in advance where you are going to collide. There are also several helper functions in KinematicBody2D, PhysicsBody2D and CollisionObject2D (inherited classes), such as move_and_slide, but I have too few knowledge of them at the moment, you may take a look :slight_smile:

Zylann | 2016-12-14 02:18

The get_travel is another method that can be used with the normal to fix or fine tune the bounce effect (everything depends on the mechanics).

http://docs.godotengine.org/en/stable/classes/class_kinematicbody2d.html#class-kinematicbody2d-get-travel


But if that entity depends too much on physics, might be better to use a rigid body and just correct minor issues with _integrate_forces.

eons | 2016-12-14 04:21

A lot of great things to look at then. Obviously I’m still fairly new to Godot, so this is really helpful stuff. Thanks again Zylann, and for chiming in as well, eons. move_and_slide looks like a great helper and I’ll explore other options as well.

akhenaten | 2016-12-15 02:05