i'm trying to create a 3d character controller that will bounce on collision, getting the bounced velocity vector is easy because the Vector3.bounce function is built-in but i'm struggling with the implementation.
the code so far is this:
func _physics_process(delta: float) -> void:
# Add the gravity.
if not is_on_floor():
velocity.y -= gravity * delta
if Input.is_action_pressed("jump") and is_on_floor():
velocity.y += JUMP_VELOCITY
var input_dir := Input.get_vector("move_left", "move_right", "move_forward", "move_backward")
var direction := (transform.basis * Vector3(input_dir.x, 0, input_dir.y)).normalized()
velocity.x = decay(velocity, direction * MAX_SPEED, 3, delta).x
velocity.z = decay(velocity, direction * MAX_SPEED, 3, delta).z
var prev_velocity = velocity
move_and_slide()
if get_last_slide_collision():
get_last_slide_collision().get_collision_count()
velocity = prev_velocity.bounce(get_last_slide_collision().get_normal(0))
# exponential decay function
func decay(a, b, decay:float, dt:float):
return b + ( a - b ) * exp(-decay * dt)
this works fine for approximately flat terrain where the normal of the collision points basically up but not for angled collisions, as far as i can tell this is because the bounced velocity is calculated at the end but only applied next physics call so it gets modified by gravity and the movement code. this results in a very weak bounce. how can i solve this?