Player's collision partially goes through ground and causes jump to be weird

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By Darxkl05

As the title said, for some reason, yesterday I started my project and noticed that I couldn’t jump normally. After that I noticed that part of my player’s collision shape went through the ground. The thing is, when I jump, the player’s collision stops going through the floor, and a second later, the player actually jumps.

I don’t recall making any significant changes to the player’s code, but I think the issue comes from there. I don’t know what could be causing this. Here’s the code:

extends KinematicBody

var speed
var default_move_speed = 9
var crouch_move_speed = 4
var run_move_speed = 19
var tired_move_speed = 4
var crouch_speed = 20 #Speed of transition between crouch and normal position and viceversa 

const ACCEL_DEFAULT = 9.5 #Changes how smoothly the player decelerates when releasing input. The bigger the value is, the more rigid the movement will be
const ACCEL_AIR = 1
onready var accel = ACCEL_DEFAULT
var gravity = 24
var jump = 9 #Jump strength/height
var height
var default_height = 3
var crouch_height = 0.8

var cam_accel = 40
var mouse_sense = 0.25 #Mouse sensitivity
var snap

var direction = Vector3()
var velocity = Vector3()
var gravity_vec = Vector3()
var movement = Vector3()
var fall = Vector3()

onready var head = $Head
onready var camera = $Head/Camera
onready var viewmodel_camera = $Head/Camera/ViewportContainer/Viewport/ViewmodelCam
onready var player_capsule = $CollisionShape
onready var bonk_detector = $CeilingRaycast

onready var CameraAnimPlayer = $Head/Camera/CameraAnimPlayer
onready var CameraAnimTree = $Head/Camera/AnimationTree.get("parameters/playback")

onready var FadeAnim = $"Head/Camera/UI-HUD/FadeInOut/FadeInOut/FadeAnim"
onready var PauseMenu = $"Head/Camera/UI-HUD/PauseMenu/PauseMenu"

onready var ViewmodelArms = $Head/ViewmodelItems/ArmsViewmodel
onready var ArmsAnimTree = $Head/ViewmodelItems/ArmsViewmodel/LEDTubeLightAnimationTree
onready var arms_state_machine = ArmsAnimTree["parameters/playback"]

onready var InventoryActive = false

#Misc
const running_sight_intro = preload("res://SFX/Player/Running sigh intro.wav") #The variable is set as const because is not going to be modified at any time. Using cons also may help when something changes the variable value automatically for whatever reason
const running_sight_loop = preload("res://SFX/Player/Running sigh loop fixed.wav") 
const tired_sight = preload("res://SFX/Player/Tired sighs.wav")



#State Machine
enum {
	IDLE,
	RUNNING,
	CROUCHING,
	JUMPING,
	MIDAIR,
	TOUCHDOWN,
	TIRED,
	DEATH,
	DEAD
}


var state = IDLE


func _ready():
	#hides the cursor
	Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
	GlobalScript.DeathType = "Normal" #Sets normal death to default death type
	
	
#------------------------------------------------------------------------
#Misc Functions


func _input(event):
	#get mouse input for camera rotation
	if event is InputEventMouseMotion:
		rotate_y(deg2rad(-event.relative.x * mouse_sense))
		head.rotate_x(deg2rad(-event.relative.y * mouse_sense))
		head.rotation.x = clamp(head.rotation.x, deg2rad(-89), deg2rad(89))

func _process(delta):
	pass
		
func Death():
	GlobalScript.movement = false
	GlobalScript.can_run = false
	GlobalScript.PauseMenuEnabled = false
	GlobalScript.InventoryEnabled = false
	
	#Collisions
	$Foot.shape.height = 0
	$CollisionShape.shape.height = 0.2

	#UI
	$"Head/Camera/UI-HUD/GameOver".visible = true
	
	#Disable viewmodel
	$Head/ViewmodelItems/ArmsViewmodel.visible = false
	
	#Mouse 
	Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE) 
	
	#Camera Movement
	mouse_sense = 0
	
	yield(get_tree().create_timer(0.5), "timeout")
	#Modify contrast through the map's environment (env node and player node must always be in the same hierarchy)
	var death_tween := create_tween()
	death_tween.tween_property($"../WorldEnvironment", "environment:adjustment_contrast", 3.0, 5.0)
	death_tween.tween_property($"../WorldEnvironment", "environment:adjustment_brightness", 2.8, 5.0)
	
	yield(get_tree().create_timer(1.5), "timeout")
	
	#Enable buttons
	$"Head/Camera/UI-HUD/GameOver/Text/Load".disabled = false
	$"Head/Camera/UI-HUD/GameOver/Text/Exit".disabled = false

	
	var death_tween2 := create_tween()
	death_tween2.set_parallel(true)
	

	death_tween2.tween_property($"Head/Camera/UI-HUD/GameOver/ColorRect", 'color:a', 1.0, 2)
	death_tween2.tween_property($"Head/Camera/UI-HUD/GameOver/Text/Title", 'custom_colors/font_color:a', 1.0, 1.5)
	death_tween2.tween_property($"Head/Camera/UI-HUD/GameOver/Text/Load", 'custom_colors/font_color:a', 1.0, 1.5)
	death_tween2.tween_property($"Head/Camera/UI-HUD/GameOver/Text/Exit", 'custom_colors/font_color:a', 1.0, 1.5)

		
func _physics_process(delta):
	var head_bonked = false
	speed = default_move_speed 
	direction = Vector3.ZERO
	
	#----------------------CAMERA---------------------------
	#camera physics interpolation to reduce physics jitter on high refresh-rate monitors
	if Engine.get_frames_per_second() > Engine.iterations_per_second:
		camera.set_as_toplevel(true)
		camera.global_transform.origin = camera.global_transform.origin.linear_interpolate(head.global_transform.origin, cam_accel * delta)
		camera.rotation.y = rotation.y
		camera.rotation.x = head.rotation.x
	else:
		camera.set_as_toplevel(false)
		camera.global_transform = head.global_transform
		
	viewmodel_camera.global_transform = camera.global_transform


#State machine
	match state:
		IDLE:
			speed = default_move_speed
			CameraAnimPlayer.play("PlayerIdleCamera")
			if is_on_floor() == false:
				state = MIDAIR
				
		RUNNING:
			CameraAnimPlayer.play("PlayerRunningCamera")
			
		CROUCHING:
			speed = crouch_move_speed
			CameraAnimPlayer.play("PlayerGetCrouchedCamera")
			CameraAnimPlayer.queue("PlayerCrouchCamera")
			
		TIRED:
			CameraAnimPlayer.play("PlayerTiredCamera")
			
		JUMPING:
			pass
			
		MIDAIR:
			if is_on_floor() == true:
				state = TOUCHDOWN
				
		TOUCHDOWN: 
			if gravity_vec.length() >= 50:
				#GlobalScript.Health - 25
				print("damage taken")
		DEAD:
			#CameraAnimPlayer.play("PlayerDeathCamera")
			CameraAnimPlayer.queue("PlayerIdleCamera")
			if GlobalScript.DeathType == "BlackOut":
				BlackOutDeath()
			else:
				Death()
	
		
#------------------------------------------------------------------------

	if bonk_detector.is_colliding():
		head_bonked = true
		
	#Movement
	if GlobalScript.movement == true:
		var h_rot = global_transform.basis.get_euler().y
		var f_input = Input.get_action_strength("move_backward") - Input.get_action_strength("move_forward")
		var h_input = Input.get_action_strength("move_right") - Input.get_action_strength("move_left")
		direction = Vector3(h_input, 0, f_input).rotated(Vector3.UP, h_rot).normalized()
		if Input.is_action_pressed("move_forward") and is_on_floor() == true:
			arms_state_machine.travel("Walking")
		if Input.is_action_just_released("move_forward") or is_on_floor() == false:
			arms_state_machine.travel("Idle")
	
	#Running
	if Input.is_action_pressed("run") and Input.is_action_pressed("move_forward") and is_on_floor() == true:
		if GlobalScript.can_run == true:
			if $PlayerAudio.is_playing() == false or $PlayerAudio.stream != running_sight_loop:
				var running_loop := create_tween()
				running_loop.tween_property($PlayerAudio, "volume_db", 12.0, 0.5) #Fade In
				$PlayerAudio.stream = running_sight_loop
				$PlayerAudio.play()
			speed = run_move_speed
			state = RUNNING
	if Input.is_action_just_released("run") or is_on_floor() == false:
		var running_loop := create_tween()
		running_loop.tween_property($PlayerAudio, "volume_db", -20.0, 0.3) #Fade Out
		yield(get_tree().create_timer(0.3), "timeout")
		$PlayerAudio.stop()
		speed = default_move_speed
		state = IDLE
		
#------------------------------------------------------------------------
	#jumping and gravity
	if is_on_floor():
		snap = -get_floor_normal()
		accel = ACCEL_DEFAULT
		gravity_vec = Vector3.ZERO
	else:
		snap = Vector3.DOWN
		accel = ACCEL_AIR
		gravity_vec += Vector3.DOWN * gravity * delta
		
	if Input.is_action_just_pressed("jump") and is_on_floor():
		if GlobalScript.can_jump == true:
			snap = Vector3.ZERO
			gravity_vec = Vector3.UP * jump
		
		
#------------------------------------------------------------------------
	#make it move (maintains movement mid-air)
	velocity = velocity.linear_interpolate(direction * speed, accel * delta)
	movement = velocity + gravity_vec
	
	move_and_slide_with_snap(movement, snap, Vector3.UP)

I would really appreciate any help

Alright, I haven’t figured out what’s causing the issue, but I noticed that the capsule not clipping. It was just that the collisions of the floor in the video were messed up.
With that in mind, I can safely say that the issue has to do with the code that controls the jumping mechanic. I’ll update whenever I find the solution

Darxkl05 | 2023-02-04 12:17

My two cents, though this may not be the same as your problem. When I was still using 3.x for my 3D games, I fought a lot with jumping. I noticed that my characters’ bounding boxes were penetrating too far into the ground on some occasions, causing bad collisions when I tried to jump. I never resolved the issue in 3.x, and I concluded that its physics implementation was fundamentally broken in that regard.

The physics subsystem in 4 has been completely rewritten, and I find it to be far superior to the Bullet physics used in 3.x. Jumping works as expected, and collision shapes behave for me as they should (as far as I’ve experienced so far).

stormreaver | 2023-02-05 19:44