stick-the-quick/props/auto_path_follow.gd

53 lines
1.5 KiB
GDScript

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)