Character goes through tiles

Godot Version

Godot 4.2.2

Question

I have CharacterBody2D moving correctly and colliding with tiles as it is intended. However, when I use my jump function it kind of “teleports” through tiles, which all have collisions correctly set up. How to solve this?

can you show us your movement script

extends CharacterBody2D

func _process(_delta):
	var direction: Vector2 = Input.get_vector("left", "right", "up", "down")
	velocity = direction * 600
	move_and_slide()

	if Input.is_action_pressed("exit"):
		get_tree().quit()
	
	#gravity and jump
	jump()
		
func coin_added():
	coins += 1
	if coins > 0:
		print(coins)

func level_end():
	get_tree().quit()
	
#gravity
func gravity():
	if !is_on_floor():
		position.y += 8
#jump
func jump():
	if Input.is_action_pressed("jump") && jump_available:
		position.y -= 200
		$Timer.start()
		jump_available = false
	else:
		gravity()
		
func _on_timer_timeout():
	jump_available = true

Using velocity will give you a smooth movement

	#gravity 
	if not is_on_floor():
		velocity.y += 8

	#jump.
	if Input.is_action_pressed("jump") && jump_available:
		velocity.y -= 200

I have tried it, but neither gravity nor jump functions work when using velocity

try this movement code instead:

extends CharacterBody2D

func _physics_process(delta):
	# Add the gravity.
	if not is_on_floor():
		velocity.y += 8 

	# Handle jump.
	if Input.is_action_just_pressed("ui_accept") && jump_available:
		velocity.y = 200
		$Timer.start()
		jump_available = false

	# Get the input direction and handle the movement.

	var direction = Input.get_axis("ui_left", "ui_right")
	if direction:
		velocity.x = direction * 600

	move_and_slide()

func coin_added():
	coins += 1
	if coins > 0:
		print(coins)

func level_end():
	get_tree().quit()

func _on_timer_timeout():
	jump_available = true

still goes through tiles

can you send a video of the behavior

It might be your tiles collision

But they work fine when I move character using Input Vector

which script did you used for this clip

Alternatively, you can change from _physics_process to _process which check more frequently

extends CharacterBody2D

func _process(delta):
	# Add the gravity.
	if not is_on_floor():
		velocity.y += 8 

	# Handle jump.
	if Input.is_action_just_pressed("ui_accept") && jump_available:
		velocity.y = 200
		$Timer.start()
		jump_available = false

	# Get the input direction and handle the movement.

	var direction = Input.get_axis("ui_left", "ui_right")
	if direction:
		velocity.x = direction * 600

	move_and_slide()

func coin_added():
	coins += 1
	if coins > 0:
		print(coins)

func level_end():
	get_tree().quit()

func _on_timer_timeout():
	jump_available = true

Okay, first of all, your main code has lot of problems for a platform game:

1: All moviment/physics related code should be done/called inside _physics_process() callback because is there when the engine do all the collision checks


2:

var direction: Vector2 = Input.get_vector("left", "right", "up", "down")
velocity = direction * 600

For a platform game use get_vector is incorrect, after all with this code if you press up or down your character will walk up and down, in this case should be Input.get_axis and in velocity you just need to set the x axis:

var direction := Input.get_axis("left", "right")
velocity.x = direction * 600



3:

if Input.is_action_pressed("exit"):
	get_tree().quit()

Not exactly a problem but could be handled better, instead check this on _process/_physics_process your should check that inside _unhandled_input callback

4:

#gravity
func gravity():
	if !is_on_floor():
		position.y += 8

#jump
func jump():
	if Input.is_action_pressed("jump") && jump_available:
		position.y -= 200
		$Timer.start()
		jump_available = false
	else:
		gravity()

Here is the biggest problem, you’re using position instead velocity, for gravity that works because is a small value so the teleport distance will also be small, but for jump the value is too high for a smooth moviment, the collision never happens because you’re not moving the character, you’re teleporting the character for a position 200 pixels above

I have tried it, but neither gravity nor jump functions work when using velocity

Jump and gravity doesn’t work using velocity in your code because in your moviment code (the 2 point that i showed) you use get_vector that will return a Vector2 and after that you use velocity = direction * 600, with that if you don’t press up or down the y value will be zero so your vertical moviment will always be zero

@pham150603 code is almost correct but need some corrections too:

extends CharacterBody2D

var jump_available = true


func _physics_process(delta):
	# Add the gravity.
	if not is_on_floor():
		velocity.y += 8 

	# Handle jump.
	if Input.is_action_just_pressed("jump") && jump_available:
		# This is wrong, for a jump you need to use negative values
		#velocity.y = 200 
		velocity.y = -200
		$Timer.start()
		jump_available = false

	# Get the input direction and handle the movement.

	var direction = Input.get_axis("left", "right")
	# This check is also wrong because if you run this code, when your press
	# left or right one time the character never stops moving when you release 
	# the keys because the velocity will only be changed when your press something
	# because if you don't press anything, direction will be 0.0 that evalutes
	# to false and never set the velocity to zero again
	#if direction: 
	velocity.x = direction * 600
	
	move_and_slide()


# This is a best approach to handle the exit input, because is only called
# after a user input instead of being called dozen of times at every frame
func _unhandled_input(event: InputEvent) -> void:
	if Input.is_action_just_pressed("exit"):
		get_tree().quit()


func coin_added():
	coins += 1
	if coins > 0:
		print(coins)


func _on_timer_timeout():
	jump_available = true

2 Likes

Thank you so much!! It works like a charm! And could you please recommend me a tutorial or resource to learn all this stuff? Like there are a lot of on YouTube but no one explicitly talking about details.

In my case i generally learn more reading the docs and by trying and error. But some good channels for you watch is:

GDQuest
gamefromscratch
KidsCanCode

Also don’t forget to mark the question as answered.

1 Like

Thanks for the advice and your time!

Thanks for your time and efforts to help!