Bobbing not smoothly resetting to ZERO

I want the bobbing to slowly go back to Vector3D.ZERO over time while not moving too fast, probably using veolcity.length()
If possible, I would like it to smoothly go back faster if you are slowly, and the time scales with the speed.
But the many attempts I made on fixing it all failed.
If you could fix it thanks in advance.
Code:

class_name Player extends CharacterBody3D

#Refences
@onready var head := $Head
@onready var cam:Camera3D

#Exports
@export_group("Speed")
@export var walk_speed:float
@export var sprint_speed:float
@export_group("Jump")
@export var jump_power:float
@export var jump_boost:float
@export_group("Physics")
@export var ground_accelaration:float=5
@export var ground_decelaration:float=5
@export var air_control:float=2
@export var gravity:float=ProjectSettings.get_setting("physics/3d/default_gravity")
@export_group("Camera")
@export var bob_freq:=2.5
@export var bob_amp:=0.1
@export var base_FOV:=80.0
@export var FOV_change:=1.5
@export var sens:=0.1


#Variables
var speed:float
var dir:Vector3
var double_jump = false


#Keep Track of Sine Wave
var t_bob = 0.0

#Lock Mouse
func _ready():
	Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
	cam = get_tree().get_first_node_in_group("player_cam")
			
#Character Rotation
func _input(event):
	if event is InputEventMouseMotion:
		rotate_y(deg_to_rad(-event.relative.x * sens))
		head.rotate_x(deg_to_rad(-event.relative.y * sens))
		head.rotation.x = clamp(head.rotation.x,deg_to_rad(-87),deg_to_rad(87))

#Movement
func _physics_process(delta):
	#Add Gravity.
	if not is_on_floor():
		velocity.y -= gravity * delta

	#Handle Jump.
	if Input.is_action_just_pressed("jump") and is_on_floor():
		velocity.y = jump_power
		velocity.x += dir.x * jump_boost
		velocity.z += dir.z * jump_boost
	
	#Handle Sprint.
	if Input.is_action_pressed("sprint"):
		speed = sprint_speed
	else:
		speed = walk_speed

	# Get the input direction and handle the movement/deceleration.
	var input_dir = Input.get_vector("left", "right", "up", "down")
	dir = (transform.basis * Vector3(input_dir.x, 0, input_dir.y))
	if is_on_floor():
		if dir:
			velocity.x = lerp(velocity.x, dir.x * speed, delta * ground_accelaration)
			velocity.z = lerp(velocity.z, dir.z * speed, delta * ground_accelaration)
		else:
			velocity.x = lerp(velocity.x, dir.x * speed, delta * ground_decelaration)
			velocity.z = lerp(velocity.z, dir.z * speed, delta * ground_decelaration)
	else:
		velocity.x = lerp(velocity.x, dir.x * speed, delta * air_control)
		velocity.z = lerp(velocity.z, dir.z * speed, delta * air_control)
	
	#Head Bob Process
	t_bob += delta * velocity.length() * float(is_on_floor())
	cam.transform.origin = _headbob(t_bob)

	#FOV
	var velocity_clamped = clamp(velocity.length(), 0.5, sprint_speed * 2)
	var target_fov = base_FOV + FOV_change * velocity_clamped
	cam.fov = lerp(cam.fov, target_fov, delta * 8.0)
	
	#Begin Movement
	move_and_slide()

# Head Bob Func
func _headbob(time) -> Vector3:
	var pos = Vector3.ZERO
	pos.y = sin(time * bob_freq) * bob_amp
	pos.x = cos(time * bob_freq / 2) * bob_amp
	return pos
#Quit
func _process(_delta: float) -> void:
	if Input.is_action_just_pressed("quit"):
		get_tree().quit()

And a image of my scene

You would have to multiply bob_amp by a component of velocity.

func _headbob(time) -> Vector3:
	var length := min(1.0, velocity.length() * 0.5)
	var pos := Vector3.ZERO
	pos.y = sin(time * bob_freq) * bob_amp * length
	pos.x = cos(time * bob_freq / 2) * bob_amp * length
	return pos

Might be worth converting this into a AnimationTree system. You can use a more complex animation, or set of animations, and set it’s blend weight by the same or similar velocity component.

1 Like

I will check this code later and experiment with AnimationTrees later.
Thank you!

Thank you, it functions but has the same issues as my attempts (No midair support and you can easily tell when it’s trying to move it back to zero)

I’m trying to avoid using more nodes like the animation tree to make a simple head bob (although it doesnt look like its gonna be simple) but if i have to i will.

I’m bumping cuz lazy and need help

yes, I think making an animation is good idea for it. But doing a linear interpolation might work too. You can find the algo in the godot manual.

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