I’m trying to make a pretty simple player movement system with stairs, but when I tried using tweens to move the player to the top of the stairs they just slide down to the right then teleport up to where they should be. How could I fix this?
extends CharacterBody2D
const SPEED = 130.0
const JUMP_VELOCITY = -200.0
const COUNTDOWN_RESET = 10
const SLIDE_STOP_SPEED = 12.0
var gravity = ProjectSettings.get_setting("physics/2d/default_gravity")
var countdown = COUNTDOWN_RESET
@onready var raycast = $Raycast
@onready var sprite = $Sprite2D
func stair_entered():
velocity.y = 5
print("entered 2")
func _physics_process(delta):
if not is_on_floor():
velocity.y += gravity * delta
countdown -= 1
else:
countdown = COUNTDOWN_RESET
var touching_floor = is_on_floor() or countdown > 0
if Input.is_action_pressed("ui_up") and touching_floor:
velocity.y = JUMP_VELOCITY
countdown = 0
var direction = Input.get_action_strength("ui_right") - Input.get_action_strength("ui_left")
velocity.x = direction * SPEED if direction != 0 else move_toward(velocity.x, 0, SLIDE_STOP_SPEED)
if is_on_wall() and is_on_floor() and direction != 0:
var stair_pos = raycast.get_collision_point()
stair_pos.y -= 2
# Disable collisions and set velocity to zero for smooth movement
set_physics_process(false)
velocity = Vector2.ZERO
var tween = create_tween()
tween.tween_property(self, "global_position", stair_pos, 1.0)
await tween.finished
# Re-enable collisions and restore velocity
set_physics_process(true)
sprite.flip_h = direction < 0
move_and_slide()
Yea, I found more docs to support that. it should be processed by the scene tree independent of the node process state.
Where is the ray collision point? That is my only other concern. I know you also modify it in the y axis.
If the ray collision is right you may need to disable the collision objects because those run on the physics server, not sure if set_physics_process(false) also stops the physics engine on that node.
I’m not by a computer with Godot if that arrow is the raycast object it’s pointing down potentially at the stairs. Okay…
… I don’t see anything wrong logically, I can image what it should do. I guess if the character goes into the stair then the raycast didn’t hit the stair properly.
I guess from the video those stairs are thin it could be missing the collision. Also it seems like it isn’t colliding when going to the left and is still remembering the last collision?
You can turn on debug collision shapes in the game this should also show the ray cast.
I turned on the Debug and figured out that the raycast doesn’t turn with the player, which was causing the left problem. So I’ve modifed the raycast to fix this problem and updated the code. I’m still not sure why the player is floating off into space, though this time they fly upward in the opposite direction then they’re facing rather than down into the floor.
extends CharacterBody2D
const SPEED = 130.0
const JUMP_VELOCITY = -200.0
const COUNTDOWN_RESET = 10
const SLIDE_STOP_SPEED = 12.0
var gravity = ProjectSettings.get_setting("physics/2d/default_gravity")
var countdown = COUNTDOWN_RESET
var stair_pos = 0
@onready var raycastr = $RaycastR
@onready var raycastl = $RaycastL
@onready var sprite = $Sprite2D
func stair_entered():
velocity.y = 5
print("entered 2")
func _physics_process(delta):
if not is_on_floor():
velocity.y += gravity * delta
countdown -= 1
else:
countdown = COUNTDOWN_RESET
var touching_floor = is_on_floor() or countdown > 0
if Input.is_action_pressed("ui_up") and touching_floor:
velocity.y = JUMP_VELOCITY
countdown = 0
var direction = Input.get_action_strength("ui_right") - Input.get_action_strength("ui_left")
velocity.x = direction * SPEED if direction != 0 else move_toward(velocity.x, 0, SLIDE_STOP_SPEED)
if is_on_wall() and is_on_floor() and direction != 0:
if raycastr.is_colliding():
stair_pos = raycastr.get_collision_point()
else:
stair_pos = raycastl.get_collision_point()
stair_pos.y -= 2
# Disable collisions and set velocity to zero for smooth movement
set_physics_process(false)
$CollisionShape2D.disabled = true
velocity = Vector2.ZERO
var tween = create_tween()
tween.tween_property(self, "global_position", stair_pos, 1.0)
await tween.finished
# Re-enable collisions and restore velocity
set_physics_process(true)
$CollisionShape2D.disabled = false
if direction < 0:
sprite.flip_h = true
elif direction > 0:
sprite.flip_h = false
move_and_slide()
So I ran your code locally and I think I found the issue. so your global_position of your character is at the center of the the character. This will be higher than the stair. so the tween thinks it needs to get the chest of your character to the collision point of the raycast. which is down.
To fix this you need to compute the height of the character and divide it in half to know where the feet of the character is. then you should add this to your stair_pos.