Breakout Style Ball in 3D issues, rigidbody3D

Godot Version

4.2.1

Question

Hello im trying to do a simple ball that never speeds up or slows down, but I’m having 2 issues with this, im hitting it with some animatable bodies and it speeds up instead of just looking the normal at the impact moment and change direction. And also after several bounces it just starts slowing down and behaving like it is in space.

I have turn down to 0 all damping forces, it has a custom 0 friction physics material.

One more thing someone could know, at some collision the ball just hugs a wall or a colliding object and doesn’t bounce correctly. Thanks anyone that knows how is it happening.

Here is the basic code, note also tried using integrate forces only but same thing applies the ball speeds up on hit and behaves erratically after some bounces. Even slowing almost completely.

func _physics_process(delta: float) -> void:
    direction = direction.normalized()
    var velocity = speed * direction * delta
    var collision = move_and_collide(velocity)
    if collision:
        print(direction)
        direction = direction.bounce(collision.get_normal())

So for some reason this makes it more reliable and resets speed if it slows down after 1 bounce. But Im still having some inconsistencies on he bounce angle an force, as well as the occasional wall hug

var direction = -Vector3.FORWARD
var speed = 0.1
var vector_speed = 1

func _integrate_forces(state: PhysicsDirectBodyState3D) -> void:
	direction = direction.normalized()
	var velocity = speed * direction
	set_constant_force(velocity * Vector3(vector_speed,0,vector_speed))
	var collision = move_and_collide(velocity * Vector3(vector_speed,0,vector_speed))
	if collision:
		direction = direction.bounce(collision.get_normal())

Also I’m using the custom integrator now

All right after a few days I managed to understand better where movement was coming from.
First this is the code:

func _integrate_forces(state: PhysicsDirectBodyState3D) -> void:
	#print(linear_velocity.length())
	direction = direction.normalized()
	var velocity = speed * direction
	var vel_min = linear_velocity.normalized() * 0.1
	var vel_max = linear_velocity.normalized() * 0.18
	linear_velocity = linear_velocity.clamp(vel_min,vel_max)

	# Alternative clamp method
	#linear_velocity = linear_velocity.normalized() * 0.1

	var collision = move_and_collide(velocity)
	if collision:
		direction = direction.bounce(collision.get_normal())
		print(linear_velocity.length())

Now the explaining, first was to stop using physics and use integrate forces, whenever you are handling the physics “manually” you should use the integrate so your changes don’t get skipped or applied at weird times and this avoids erratic behavior.

Second was understanding that linear_velocity is the vector responsible for the movement, not the “force” you apply to the rigidBody3D and you can clamp it like any other vector. On my code I used two ways of clamping I found on this thread How to Clamp velocity?

Now to my other issue the boards hitting the ball

As you can see I have two RemoteTransform3D on my player and two PaletR and L(boards) on the tree.

Inside my player I can twist this remote transforms and they move the AnimatableBody3Ds. If you read on the documentation it says animatables transfer their linear velocity to other rigidBodies, it is still a bit glitchy but they hit the ball accelerate it.

I want to come back and add the code to this boards hitting the ball bc I think if you want your ball to accelerate just for a while this way I’m doing it is still not good imo.

Hopefully someone will come along with and idea/solution if not I will post my final approach next.

So after almost 2 weeks I understood what is going on. On my last block of code I was accessing linear_velocity every frame which is bad, even says it on the docs, why? because on top of my move_and_collide the physics engine will use linear_velocity too, specifically when hitting the ball with an AnimatableBody3D, so I was getting this weird behaviors on all my hits.

I understood this by lowering my speed to 0 and noticing that if I hit the ball it will move independently of the move_and_collide, with this I came up with this code.

It has two if statements that will only access and modify the linear_velocity once instead of every _integrate_forces event, this effectively clamp the movement of my ball when it goes above/below my values and keeps it moving “forever”.

When I hit the ball the calculations are left alone to speed up then clamp the max value and let it slow down. I feel is a delicate balance of the physics, forces and move_and_collide but is behaving exactly like a breakout ball. Hope this helps someone down the road.

func _integrate_forces(state: PhysicsDirectBodyState3D) -> void:
	direction = direction.normalized()
	var velocity = speed * direction
	var collision = move_and_collide(velocity)
	if collision:
		direction = direction.bounce(collision.get_normal())

	if linear_velocity.length() < min_value:
		linear_velocity = linear_velocity.normalized() * _min_value
	if linear_velocity.length() > max_value:
		linear_velocity = linear_velocity.normalized() * max_value