You could use a tween to bounce the camera when you land.
That requires two things:
- detecting when you land
- bouncing the camera
Modifying MovementController.gd in the template you're using to something like this might work. It's untested and I'm assuming that the camera always sits at its local position. If it's not working, you'd need to rework it so there's a CameraRoot with a Camera3D child and the system moves the CameraRoot around so we're free to animate the Camera3D.
@export var camera : Camera3D
@export var springy_leg_distance := 0.5
@export var springy_leg_seconds := 0.7
var _was_on_floor := false
var _camera_tween
func _physics_process(delta: float) -> void:
input_axis = Input.get_vector("move_back", "move_forward", "move_left", "move_right")
direction_input()
if is_on_floor():
if Input.is_action_just_pressed("jump"):
velocity.y = jump_height
if _was_on_floor:
# (1) At this point, we went from not on floor to on floor, so we
# want to bounce.
# We might also want to scale the amount of bounce by our
# *previous* downward velocity.
_play_camera_ground_impact()
else:
velocity.y -= gravity * delta
accelerate(delta)
# is_on_floor returns a different value after calling move_and_slide
_was_on_floor = is_on_floor()
move_and_slide()
func _play_camera_ground_impact():
# (2) Fire off a tween to bounce the camera to give a springy legs effect.
if _camera_tween:
# Prevent two overlapping tweens.
# You may want to stop if you stop touching the ground too.
_camera_tween.stop()
_camera_tween = get_tree().create_tween()
# Assuming default local position is zero!
camera.position = Vector3.DOWN * springy_leg_distance # start down a bit
_camera_tween.tween_property(
camera,
"position",
Vector3.ZERO, # tween back up
springy_leg_seconds)
_camera_tween.start()
You could also use an animation to have more control over the motion of the camera.