# Help understanding 3D velocity, .bounce(), and move_and_collide

4.2

### Question

I’m working on a 3D brick breaker game (game uses the x and z axis for movement). I want to give the option for the player to have arkanoid like physics when hitting the paddle or standard breakout ones. I can easily let the player pick the option and change how the ball acts when hitting the paddle. However, the actual physics is where I’m having a bit of trouble. Can someone help me out?

The ball is a CharacterBody3D (floating mode) (not opposed to rigidbody, but with me wanting to potentially alter the physics CharacterBody3D seemed like the better choice). Here’s the relevant code:

``````func _physics_process(delta):
var ball_speed = velocity * SPEED * delta
var collision_object = move_and_collide(ball_speed)

if collision_object:
var collider = collision_object.get_collider()
var normal = collision_object.get_normal()
var reflect = collision_object.get_remainder().bounce(collision_object.get_normal())

if collider.is_in_group("BRICKS"):
#print(collider.get_parent())
#collider.queue_free()
brick_collision.emit(collider)
#ball_collision(collider)
collider.apply_central_impulse(-normal * push_force)
#collider.take_damage(1)

velocity = velocity.bounce(normal)
move_and_collide(reflect)

var arkanoid : Vector3 = paddle_collision(collider)
velocity = arkanoid * (SPEED * 1.5) * delta

else:
velocity = velocity.bounce(normal)
#print(velocity)
#print(reflect)
move_and_collide(reflect)

var ball_center = position

var direction : Vector3
direction.x = (ball_center.x - collider.position.x)
direction.z = (ball_center.z - collider.position.z)
direction.y = 1.5 // only using X and Z planes, Y will stay constant)

return direction
``````

I’ll clean this up as I go to make it clearer that BRICKS and other objects use the same collision code. The code for the standard reflection is straight from Godot docs.

I believe this will give me the reflection like I expect for the walls and bricks.

Part of what I’m not understanding is why I do `velocity.bounce(normal)` then call `move_and_collide` again. Why do I want to call bounce then move and collide? Can someone tell me a bit more about what bounce is calculating? I couldn’t really find much in the docs about what it actually does underneath.

Secondly, for when a collision with a paddle happens. The returned `direction` Vector3 is giving me pretty close to the angle I want (at least I think it is). But the ball slows down a lot. I’m a bit unsure of how I can get it to speed back up. I tried scaling the vector with SPEED and even multiplying SPEED by 1.5. I’ve tried a similar approach of adding the `velocity = velocity.bounce(nromal)` and then `move_and_collide(arkanoid)` but the angles don’t end up being right. Any tips or guidance here would be appreciated!

I do have vector math, trig, and linear algebra on my list to learn more about, I’m just not as sure within those where the answer to this would be.

Currently using Jolt as having the ball roll around with standard physics seemed to give me pretty rough FPS even at a very basic prototype. I’ll also take any tips there if anyone has any thoughts on improving the performance with Godot base physics if possible.

Imagine that you’ve asked to move the ball 1 meter (that is of course too far to move on a single frame, but it’s a simple number to work with).

However, 0.6 meters along its path, a collision is detected, which stops the ball. Now it has only moved just over half a meter! That means that, in order to keep the ball at a consistent velocity, it still has to move another 0.4 meters on this frame. The second `move_and_collide` call moves it this remaining distance, in whatever direction we’ve decided to bounce it.

Try normalizing it:

``````var arkanoid : Vector3 = paddle_collision(collider)
velocity = arkanoid.normalized() * SPEED
``````

Normalizing a vector means setting its length to 1, while keeping its direction. So with the above code, the ball would move with the default speed defined in the `SPEED` variable. Alternatively, you could save the speed it was at when it hit the paddle and use that.

Also, you shouldn’t multiply with `delta` when setting the `velocity`, because you are already multiplying with `delta` at the start of the `_physics_process` function (when you define `ball_speed`). You probably don’t wanna multiply with `delta` twice.

Oh yeah, and `bounce` basically does this:

Here:

• v1 is the vector we’re bouncing
• we’re using the normal vector of the plane represented by the black line
• v2 is the result
• v1 and v2 have the same length (yeah I know they don’t in the drawing, I made it in paint in 2 minutes)
• the angles A and B are the same

Got ya. So then I call move_and_collide with that velocity value I just set? Based on your other post, I’m unsure if I should include bounce since the angle the ball leaves will be based on where it hits the paddle as opposed to the incoming angle.

``````velocity = arkanoid.normalized() * SPEED
move_and_collide(velocity)
``````

I think this is working! I had tried normalizing the vector before, but had included bounce or tried other things. I hadn’t just applied it to the velocity and called move_and_collide

Also, thanks for the tip on not needing to include delta again. I had done so because without it my ball would get so fast it would go outside the level. I think this was a combination of the velocity being too high and me not normalizing the vector possibly.

Hmm. In the other branches you are calling it with the `reflect` vector, which is the remaining movement that didn’t get to happen (because of the collision), but bounced. You probably want to do something similar:

1. Calculate the remaining distance to be moved
2. Calculate the direction to move using your `paddle_collision` function
3. Normalize the direction and multiply it with the remaining distance, and then use that to `move_and_collide`
4. Set the velocity to the new direction (normalized), multiplied by the speed you want it to move at. This will then be used on the next frame.

Thanks. I tried this two different ways. using `arkanoid_reflect` doesn’t work at all. I suspected not, but wanted to try it out to see what would happen, from what I can tell, not much.

`new_direction` does reflect the ball, however, something about the remainder or the way I’m getting the remainder is making the new vector pretty unpredictable. When coming in at very similar angles and hitting the same space on the paddle, the new angle can be totally different.

``````var remainder : Vector3 = collision_object.get_remainder()
var new_direction : Vector3 = arkanoid.normalized() * remainder
var arkanoid_reflect : Vector3 = collision_object.get_remainder().bounce(arkanoid.normalized()) * SPEED

move_and_collide(new_direction)
velocity = new_direction.normalized() * SPEED
``````

I’ll also head back to your first answer and mark this as solved as you’ve definitely helped me understand the base questions I had!

I think the problem with `arkanoid_reflect` is that you’re trying to use `arkanoid` (which at least in your previous code was the movement direction you wanted for the ball) as a normal vector of a plane to bounce against - those are two different things.

Try this for `new_direction`, since multiplying two vectors will just give you the component-wise product, which is not what you want:

``````var new_direction : Vector3 = arkanoid.normalized() * remainder.length()
``````
1 Like

Thanks so much for your help. Worked as expected. Instead of using SPEED I also simply multiplied the new vector by velocity.length() and that retained my velocity. I could then multiply by a speed up factor and have an overall limit on velocity for the ball too.

Final setting for the ball’s velocity:

``````velocity = (new_direction.normalized() * velocity.length() * speed_up_factor).limit_length(VELOCITY_LIMIT)
``````

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.