class_name AutoPathFollow extends PathFollow3D @export var speed: float = 1.0 @export var pause_at_ends: float = 1.0 @export var body: AnimatableBody3D @export var area: Area3D @onready var _prev_position := global_position @onready var _area_bodies: Array[Character] = [] var direction: float = 1.0 var pause_timer: float = 0.0 func _ready() -> void: if area: area.body_entered.connect(_on_area_body_entered) area.body_exited.connect(_on_area_body_exited) func _physics_process(delta: float) -> void: if pause_timer > 0.0: pause_timer -= delta else: progress += direction*speed*delta if !loop && ( (direction > 0.0 && progress_ratio >= 1.0) || (direction < 0.0 && progress_ratio <= 0.0) ): progress_ratio = clamp(progress_ratio, 0.0, 1.0) direction *= -1.0 pause_timer = pause_at_ends var velocity := (global_position - _prev_position).normalized()*speed _prev_position = global_position if body: body.global_position = global_position body.constant_linear_velocity = velocity for ch in _area_bodies: if ch.impetus.is_zero_approx() && ch.is_grounded(): ch.state = &'idle' var veldiff := velocity - ch.linear_velocity veldiff -= veldiff.project(global_basis.y) ch.apply_central_impulse(ch.mass*veldiff) func _on_area_body_entered(pbody: Node3D) -> void: var ch := pbody as Character if ch && _area_bodies.count(ch) <= 0: _area_bodies.push_back(ch) func _on_area_body_exited(pbody: Node3D) -> void: var ch := pbody as Character if ch: while _area_bodies.count(ch) > 0: _area_bodies.erase(ch)