I’m making a kart like game, I was testing some barriers, then I implemented that when the kart collided with a barrier it should bounce a bit, at first it worked, but the bounce was really small, so, I multiply it by 25, now the bounce is fine. However, when I bounce in not a straight direction it sometimes makes me fly away XD, I found that sometimes Vector3.bounce() returned an unusual high value, I don’t know why, it is my first time using 3D physics, what is happening? is it a bug? What I’m making wrong?
The code is:
func _physics_process(delta):
if ray_cast_3d.is_colliding():
var with = ray_cast_3d.get_collider()
if is_instance_valid(with):
with.get_parent().queue_free()
set_helmet()
# Adds the gravity.
if not is_on_floor():
velocity += get_gravity() * 5 * delta
# Handles jump.
if Input.is_action_just_pressed("ui_accept") and is_on_floor() and can_move:
velocity.y = JUMP_VELOCITY
# Impulse
if Input.is_action_pressed("X") and can_move:
direction = -transform.basis.z.normalized()
velocity = velocity.move_toward(direction * SPEED, ACELERATION * delta)
turning_velocity = move_toward(turning_velocity, TURNING_SPEED, TURNING_ACELERATION * delta)
else:
velocity = velocity.move_toward(Vector3.ZERO, DERRAPE * delta)
turning_velocity = move_toward(turning_velocity, 0, TURNING_DERRAPE * delta)
# Turning
if velocity != Vector3.ZERO and can_move:
if Input.is_action_pressed("ui_left"):
rotate_y(deg_to_rad(turning_velocity * delta))
elif Input.is_action_pressed("ui_right"):
rotate_y(deg_to_rad(-turning_velocity * delta))
#print(velocity)
var col = get_last_slide_collision()
if col:
if col.get_collider().get_owner().is_in_group("SolidObject"):
velocity = velocity.bounce(col.get_normal()) * 25
print("bounce community ",col.get_normal()," / ",velocity)
move_and_slide()
here is a video where the bug occurs:
(ignore that the print says “bounce community” to show the results)
The reason for your problem is that the velocity of a colliding body is post-contact. This means that “straight collisions”, where the physics body is at a near stand-still, produce velocities that are small. On the contrary, oblique collisions barely affect the velocity of a moving physics body so the velocity maintains most of its length.
If you wish to bounce your vehicle based on the entry velocity, not the post-contact velocity, you have to store a velocity history.
var previous_velocity = Vector3.ZERO
func _physics_process(delta):
# =================
# === Your code ===
# =================
# [End of function]
previous_velocity = velocity
It’s not bounce() returning a high value – it’s you multiplying the value by 25. Besides, bounce() doesn’t manipulate the length of the vector, it just computes its reflection vector for a given plane normal. Just don’t multiply by 25. You will find that using the previous_velocity, as outlined above, will yield better results.
In cases of inaccurate bounce directions
Depending on your turning speed and delta time of your physics, you may start to notice that previous_velocity does not correctly represent the body’s direction one tick later. That is, of course, because it’s an “old” value.
You can fix this by extrapolating the previous_velocity vector towards the current state of your body. An example of such extrapolation can be found here.
I hope that helps. Let me know if you have additional questions.
Thanks! for your comment, sorry for responding too late. I couldn’t test it yet, but now I understand what is happening. I will let you know when I implement it.
I’ve tested it and finally works! Also was necessary to change the order or my collision code, now it is calculated before move_and_slide(). Thanks so much! UwU
move_and_slide()
var col = get_last_slide_collision()
if col:
if col.get_collider().get_owner().is_in_group("SolidObject"):
velocity = last_velocity.bounce(col.get_normal())
last_velocity = velocity