Unsure if I'm incorrectly using get_real_velocity()

Godot Version

Godot Engine v4.3

Question

I have a CharacterBody3d that I want to jump the moment that it detects that it’s collided with the floor. I want the jump force to be added to the ‘real’ y velocity so the player gets less height when walking down a slope and more height if they’re walking up a slope. Here’s a stripped down version of what I’m trying to add:

var gravity = ProjectSettings.get_setting("physics/3d/default_gravity") # 22
var wish_jump: bool = false
var last_y_vel: float

func _physics_process(delta: float) -> void:
	var vel: Vector3 = get_velocity()
	queue_jump() # sets wish_jump 
	
	if is_on_floor() and last_y_vel != 0: # show last y velocity after hitting floor
		print(last_y_vel) 
	
	if is_on_floor():
		if wish_jump:
			wish_jump = false
			vel.y += jump_force #+ last_y_vel
		else:
			vel.y = 0
		 
	else: # in the air 
		vel.y -= gravity * delta
	
	velocity = vel
	move_and_slide()
	
	last_y_vel = get_real_velocity().y 

I was hoping that the moment that the player touches the floor in this case, their y velocity during the physics tick should be zero.
In reality, when is_on_floor() returns true, the previous call to get_real_velocity() returns -5.31, 0.30, 0.03 for each subsequent call of the physics process. I can’t tell if get_real_velocity() returns the difference of how far the player traveled last move, or the vector of the remaining motion, or something else that I’m not understanding.

I’m new to pretty much all of this, so I’m unsure if I’m not using the method correctly or missing some other way to go about solving my problem, so any help would be greatly appreciated!

I’ve tried something similar with get_real_velocity() when creating a “launch” jump when sliding up a ramp. I found that I had to store the velocity from the previous frame to use in the calculation because it would be overwritten the next frame, which you should try since the player hitting the floor would cancel any y velocity.

In any case, be sure to use the DebugDraw3D plugin to visualize the velocity vector on your player. It makes debugging way easier.

I suppose I found with certainty what’s happening. Looking at the source code shows that get_real_velocity() returns the difference in position from before and after move_and_slide(), which is why I was getting a negative value when it was called after hitting the floor.

My solution to my problem has been to test vel’s movement with move_and_collide() before calling move_and_slide(). The check will see if it collided with anything, and get the y component of the remaining velocity after it’s projected along the plane the player collided with.

motion = vel
col = move_and_collide(motion * delta, true)
	if col: 
		n = col.get_normal()
		projection = col.get_remainder().slide(n)
		return projection
	else: 
		return Vector3.ZERO

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