Cant make player move with the platform

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.

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