How to make a dynamic vault system

I want a vault system with as little possible ray casts. I’m assuming you would shoot a ray from your feet and then from the head, and rotate it slightly up.

Then you would vault if the feet ray is touching while the top isn’t but I want it so you can vault things that are above you and might not be hitting your foot ray (think smash bros platform)

I legitimately don’t know how to do this i can’t sleep help me 🫨

Wow this is pretty good timing i just made a vault system of my own. Well Vault/Wallclimb thing.

It works using 3 Raycasts:
1: Raycast that horizontally follows player view - used for determining the distance from the obstacle
2: Raycast that follows player view (horizontal and vertical) - actually this one has no purpose…
3: Final Downward Raycast - casts down from point above obstacle, determines if player can vault or not

Raycast 3 is moved every frame so it is above the point where raycast 1 is colliding with the obstacle

Here’s a sketch thing i did for the math:


(might be a bit confusing, didn’t really intend on it being viewed by someone)

If you need help implementing it i can show my code and stuff, lmk

3 Likes

If possible I’d like to have access to the source code cuz I don’t understand how the margin of the first and second raycast work.

Ofcourse if you aren’t comfortable sharing it I just need some clarification of how you place and move each raycast, and how you use them to determine if you can vault in the first place. :pray:

1 Like

It’s pretty basic in principle (in practice it can get a bit tricky tho, you’ll see later)

You have a point marked with an X, defined as:

var wish_dist : float = 3.0 # arbitrary value for now
var x_point : Vector3 = cam.global_position + -cam.global_basis.z * wish_dist # camera position + forward camera vector * distance

And you also have your Vault Raycast.
image


(note that top level is toggled on)

Then you position your Vault Raycast at the X point, looking down.

var vault_raycast : Raycast3D = %VaultRaycast # example variable for the raycast
...
func _physics_process(delta):
	var wish_dist : float = 3.0 # arbitrary value for now
	var x_point : Vector3 = -cam.global_basis.z * wish_dist # forward camera vector * distance
	vault_raycast.global_position = x_point

And then when the player presses a button or smth, you move the player to the collision point if the raycast is colliding

func _input(event):
	if Input.is_action_just_pressed("vault"):
		if vault_raycast.is_colliding():
			# do the vault thing
			self.global_position = vault_raycast.get_collision_point() + Vector3.UP*1.0

This is the basic functionality, if the player looks above an obstacle and it’s close enough, they can vault on top of it.

If you want a complete rigid system you’ll need to make 2 improvements:
1 - Lerping the player to the point
2 - Adjusting the X point distance while accounting for the obstacle dimensions

For the first improvement you simply lerp the player to the position, and do other adjustments as necessary (for example; i used a timer to limit the maximum time of the lerp, teleporting the player on timer timeout, just in case the player gets stuck or something, you could also make the player phase thru walls, or smth else, honestly didn’t experiment much with this part)

For the second improvement, this one is pretty important and tricky.
So, obstacle dimensions and their distance from the player can vary, and you’ll need to account for it.
For example:
image
Here we’d want to move the X point closer to the player, so he can simply vault onto the wall.
image

The approach i’d think of using is firing a shapecast, getting the collision point and determining the wish distance using that.
image
Or maybe you could use a raycast at the feet of the player however that wouldn’t play nice with slopes.
At the time of my first post i was using a raycast at the player’s eye line, because my mechanic was supposed to be a wallclimb thing, but i’m gonna try to switch to the shapecast approach, however i think this one isn’t perfect either, atleast without further adjustments.

Also just read that ur post is about C#, sorry but i have no idea how to work with it, hopefully you can translate the gdscript code.


// EDIT: wow it was really easy switching to a shapecast, welp i can actually help with the 2nd part too now

So i made a shapecast, parented it to player’s head so it only follows his horizontal look rotation
image
I moved it a bit forward so it doesn’t hit the player, too lazy to mess with collision layers

Then when calculating the X point, you add some stuff

var coll_point = %VaultObstacleShapeCast.get_collision_point(0)
var dist = (head.global_position - Vector3(coll_point.x, head.global_position.y, coll_point.z)).length()
var angle = min(cam.rotation.x, vault_max_angle) # we use min to clamp the cam.rotation.x to a maximum of "vaul_max_angle", used this bcs the wish_dist rises exponentially as the angle rises, see image under code

# after getting the angle between look vector and horizontal forward vector
# we can calculate the projected distance using trigonometry, explanation under the code
var wish_dist = dist/cos(angle)

var x_point = cam.global_position - cam.global_basis.z * (wish_dist + vault_target_pos_offset) # we also move it a bit further using "vault_target_pos_offset", so it's a bit away from the edge, if it was right on the edge i think the vault raycast sometimes wouldn't collide
# but now we also have to account for the change in the height of the X point, by lengthening the vault cast target_position.y according to the distance of the 3rd side of the triangle, which we can calculate using the pythagorean theorem
vault_cast.target_position.y = -sqrt(pow(wish_dist, 2.0) - pow(dist, 2.0)) - 1.0

image
image


// EDIT 2: I’ve encountered issues caused by the shape of the shapecast
For example the thickness causing the wish distance to be short when a wall is hitting the side of the shape:
image
So i’ve changed it from a sphere to a cube, with X size of 0.001

Now it works great in most situations, if you find any other edge cases, lmk and i can maybe help with solving them

1 Like

Wow, thank I’m sure this will help many ppl!
I’m prolly gonna reread this 100 times cuz my brain is the size of a pea but thanks! :blush:

Edit: I just saw that you just saw that my post was about C#, it isn’t. But my thumbs fat fingered it when I was choosing them on my phone, don’t worry about it :+1:

1 Like

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