godot-FirstPersonStarter icon indicating copy to clipboard operation
godot-FirstPersonStarter copied to clipboard

Retain velocity when jumping from moving platforms

Open zvodd opened this issue 1 year ago • 0 comments

If the player is standing on a moving platform, they will come to a halt in the air when jumping. This is because air control causes deceleration towards 0 velocity, hence stopping dead in the air when there is no input. I've been attempting to implement a fix in the Movement Controller. No luck so far...

I can make it work by removing all air control and simply keeping and applying the x & z velocity upon jumping.

I think, In theory its a matter of taking into account the velocity the time of jump and making the deceleration relative to that.

Splitting the air and ground integration may help:

# Called every physics tick. 'delta' is constant
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
			velocity_on_jump = Vector3(velocity.x, 0, velocity.z)
		accelerate_ground(delta)
	else:
		velocity.y -= gravity * delta
		accelerate_air(delta)
	
	move_and_slide()

func accelerate_ground(delta: float) -> void:
	# Using only the horizontal velocity, interpolate towards the input.
	var temp_accel: float
	var temp_vel := Vector3(velocity.x, 0, velocity.z)
	var target: Vector3 = direction * speed
	
	if direction.dot(temp_vel) > 0:
		temp_accel = acceleration
	else:
		temp_accel = deceleration
	
	temp_vel = temp_vel.lerp(target, temp_accel * delta)
	
	velocity.x = temp_vel.x
	velocity.z = temp_vel.z

func accelerate_air(delta: float) -> void:
	# Using only the horizontal velocity, we just leave it untouched I guess
	var temp_accel: float
	var temp_vel := Vector3(velocity.x, 0, velocity.z)
		
	velocity.x = temp_vel.x
	velocity.z = temp_vel.z

zvodd avatar May 11 '23 15:05 zvodd