Custom Collision Using ShapeCast

Godot Version



Hey all, for a project I was using the CharacterBody3D’s move_and_slide function to move my character like one would however, when the player was up against a wall they would start to jitter along it causing the player to stop and start. After trying to fix the issue to no avail a decided to shoot my shot with writing some custom collision code.

I came across this video and wanted to see if I could implement something like it into godot.

What I have seems to mostly work but the problem I’m running into is that the shapecast seems to go through a wall if it is right up against it. I’m not sure why that would be the case since I move the player to the point right before the collision and then move them back a small distance. This distance should be enough for the shape cast to register the wall but I guess not. So I’m kind of stuck on this.

Here is my code below, but I’m not sure if just seeing it would be enough to help me with my issue so here is a link to a GitHub I made with just the bare bones of my project.

Lets me know if there are any issues, I am really scratching I’m head here.

var skin_width = 0.02; #Small amount that keeps the player form clipping into walls.
#Shape cast in the direction of the velocity.
shape_cast.target_position = shape_cast.position + velocity;
#If the shape cast has NOT collided.
	#print("Shape cast did not collide.")
	global_position += velocity;
#Otherwise a collision has occurred!
print("\nShape Cast Collided!")
#First, find the distance to move the player.
var fraction:float = shape_cast.get_closest_collision_safe_fraction(); 
var vel_to_surface:Vector3 = velocity * fraction; #Velocity needed to move the player to the surface.
vel_to_surface -= velocity.normalized() * skin_width; #Subtract the skin width from the velocity so that the play does not clip into the surface.
print("Distance to surface: " + str(vel_to_surface.length()));
#Second, move the player to the point right before the collision.
if(vel_to_surface.length() > skin_width):
	global_position += vel_to_surface;