PathFollow2D problem

Godot Version

4.6.1

Question

I was implementing a charecter: Policeman in my game, that would move around a PathFollow2D and when an area named detector will overlap a player, he’ll approache him, while being reparent to the node of the curent scene. When he’ll no longer see the player he’ll return to the path and again become a child of PathFollow2D. The problem is that when he returns to be a child of PathFollow2D he doesn’t moves exactly around the seted path and because of it, he’ll often just stay around wall, trying to move forward.

Here is the Policeman’s code:


class_name Policeman extends CharacterBody2D

var speed:=300.0
var direction:Vector2
var player:Player=null
var last_progress:float
var tween:Tween
var has_detected:=false
var times_player_captured:=0
@onready var detector: Area2D = $Detector
@onready var hitbox: Area2D = $Hitbox
@onready var rich_text_label: RichTextLabel = %RichTextLabel
@onready var new_parent = get_tree().root.get_node("Prison")
@onready var parent=get_parent()

func _ready() -> void:
	rotation=90.0
	rich_text_label.hide()
	detector.body_entered.connect(_on_body_entered)
	hitbox.body_entered.connect(_on_body_entered_hitbox)

func _on_body_entered_hitbox(body:Node2D)->void:
	if body == player or body is HitArea or body is Gates:
		times_player_captured+=1
		DaysCounterScript.days+=1
		new_parent.timer.start()
		get_tree().call_deferred("reload_current_scene")

func _on_body_entered(body: Node2D) -> void:
	if body is Player:
		player=body
		speed=400.0+times_player_captured*5
		last_progress = parent.progress_ratio
		call_deferred("reparent",new_parent,true)
		rich_text_label.show()
		rich_text_label.text="POLICEMEN HAS DETECTED YOU!"
	elif body.is_in_group("to_detact") or has_detected:
		player=get_tree().root.get_node("Prison/Player")
		speed=425.0+times_player_captured*10
		last_progress=parent.progress_ratio
		call_deferred("reparent",new_parent,true)
		if body is Dead_npc:
			rich_text_label.show()
			rich_text_label.text="POLICEMEN HAS DETECTED DEAD PRISONER!"
		elif body is Wall_Area:
			rich_text_label.show()
			rich_text_label.text="POLICEMEN HAS DETECTED YOUR DEMAGED WALL!"
		elif body is Explosion:
			rich_text_label.show()
			rich_text_label.text="POLICEMEN HAS HEARD THE EXPLOSION!"

func _physics_process(_delta: float) -> void:
	if player:
		direction=global_position.direction_to(player.global_position)
		velocity=direction*speed
	if player and not player.hidden.is_connected(_player_hidden):
		player.hidden.connect(_player_hidden)
		has_detected=false
	move_and_slide()

func _player_hidden() -> void:
	player = null
	call_deferred("reparent", parent, true)
	speed = 270.0 + times_player_captured * 10
	parent.progress_ratio = last_progress
	rich_text_label.hide()

Here is the Path’s code:

extends PathFollow2D

var policeman:CharacterBody2D

func _ready() -> void:
	policeman=get_child(0)

func _process(delta: float) -> void:
	if get_child_count()>0:
		progress+=policeman.speed * delta

I think your policeman var in the follower is nulling out when you re-parent. So then the move code doesn’t work.

I tried to fix it by asigning policeman’s node to var and also cheching if var is null by using pring. It turned out that its never null.

extends PathFollow2D

var policeman:CharacterBody2D

func _ready() -> void:
	policeman=get_child(0)
	child_entered_tree.connect(func(child:Node2D)->void:
		if child is Policeman:
			policeman=get_child(0))

func _process(delta: float) -> void:
	print(policeman)
	if get_child_count()>0:
		progress+=policeman.speed * delta