Vic98lg
November 16, 2025, 2:38pm
1
Godot Version
4.5.1.stable
Question
I made a platform (AnimatableBody2D) with Sync to Physics On, and i made a Path2D and PathFollow to move it. But when the player is on the platform, it doesnt stick to it. I dont want to code it, it must be an easier way to do it, but i tried all. I also added a RemoteTransform2D following a tutorial, but still doesnt work. Can anyone help me?
Make sure your player is set to motion mode grounded and using move_and_slide.
AnimatableBodies have a strange bug where updating their transform more than once per frame doesn’t properly calculate the physics motion; this could be changing position and rotation separately for example.
RemoteTransform2D on it’s own may work well, otherwise use your script to only update position, or calculate a Transform2D to replace the platform’s in one assignment.
Vic98lg
November 17, 2025, 9:03am
3
Hello, thanks for your help. My character is in Grounded mode and im using this script:
extends CharacterBody2D
@export var speed: float = 220.0
@export var jump_force: float = 420.0
@export var gravity: float = 1000.0
@export var low_jump_gravity: float = 1800.0
@export var wall_jump_force: float = 420.0
@export var wall_jump_horizontal_impulse: float = 260.0
@export var wall_slide_speed: float = 60.0
@export var tiempo_entre_golpes: float = 0.6
@export var anim: AnimatedSprite2D
@export var golpe_ray: RayCast2D
var jump_count: int = 0
const MAX_JUMPS := 2
var dir: int = 1
var puede_golpear: bool = true
var en_pared: bool = false
func _physics_process(delta: float) -> void:
var input_dir = Input.get_axis("move_left", "move_right")
velocity.x = input_dir * speed
# --- Flip horizontal ---
if input_dir != 0:
dir = sign(input_dir)
anim.flip_h = dir < 0
en_pared = is_on_wall() and not is_on_floor()
# --- GRAVEDAD / WALL SLIDE ---
if en_pared and velocity.y > 0:
# deslizarse lentamente por la pared
velocity.y = min(velocity.y, wall_slide_speed)
anim.play("wall_jump")
elif not is_on_floor():
if velocity.y < 0 and not Input.is_action_pressed("jump"):
velocity.y += low_jump_gravity * delta
else:
velocity.y += gravity * delta
else:
velocity.y = 0
jump_count = 0
# --- SALTOS ---
if Input.is_action_just_pressed("jump"):
if en_pared:
# Wall jump sin limitación de lado
anim.play("wall_jump")
var wall_dir = -1 if get_wall_normal().x > 0 else 1
velocity.y = -wall_jump_force
velocity.x = wall_jump_horizontal_impulse * wall_dir
elif jump_count < MAX_JUMPS:
# Salto o doble salto
velocity.y = -jump_force
jump_count += 1
if jump_count == 1:
anim.play("jump")
else:
anim.play("double_jump")
move_and_slide()
# --- ANIMACIONES ---
if en_pared and not is_on_floor():
anim.play("wall_jump")
elif not is_on_floor():
if velocity.y > 0:
anim.play("falling")
elif jump_count == 2:
anim.play("double_jump")
else:
anim.play("jump")
else:
if input_dir != 0:
anim.play("running")
else:
anim.play("idle")
# --- ACTUALIZAR RAYCAST ---
golpe_ray.target_position = Vector2(-20 * dir, 0)
golpe_ray.force_raycast_update()
func _input(event):
if event.is_action_pressed("atacar") and puede_golpear:
atacar()
func atacar():
puede_golpear = false
golpe_ray.force_raycast_update()
if golpe_ray.is_colliding():
var objeto = golpe_ray.get_collider()
if objeto.is_in_group("cajas"):
objeto.golpeada()
await get_tree().create_timer(tiempo_entre_golpes).timeout
puede_golpear = true