Reference in child node script to parent class variable keeps resetting.

Godot Version

v4.6.1

Question

Hello all, I’ve been following this tutorial by StayAtHomeDev (https://www.youtube.com/watch?v=L5ObCs9OMRY). I’ve got to roughly the 26 minute mark and run into issues with the StateChart node and some associated scripts.

The relevant bits of my node structure are

PlayerController (player_controller.gd)
|> (Mesh, Collision, Cameras etc)
|v StateChart (https://godotengine.org/asset-library/asset/1778)
 |> Idle (atomic (single) state, sends a signal)
  |> OnMoving (transition to Moving on event "onMoving")
 |> Moving (atomic state)
(generic nodes)
|v StateMachine (state_machine.gd) 
 |v MovementState (base_state.gd)
  |v GroundedState
   |v IdleState   (idle_state.gd)

Essentially I’m trying to reference a Vector2 value defined in player_controller.gd from the child node IdleState. This lets idle_state.gd send an event to the transition node OnMoving, which will update the state chart to say the player is moving, and this will let me do more logic that’ll come later in the tutorial. My root node handles basic movement stuff and is supposed to pass values down to the child nodes.

player_controller.gd:

class_name PlayerController extends CharacterBody3D

var _input_dir : Vector2 = Vector2.ZERO

func _physics_process(delta: float) -> void:
	# (Apply gravity, handle jump)
	
	# get WASD input vector
	var _input_dir := Input.get_vector("player_strafe_left", "player_strafe_right", "player_forward", "player_backward")
	
	# (lerp velocity, apply new velocity) 
	
	move_and_slide()

state_machine.gd:

class_name PlayerStateMachine extends Node

@export var player_controller : PlayerController

base_state.gd defines PlayerState and gives player_controller to idle_state.gd later:

class_name PlayerState extends Node

var player_controller : PlayerController

func _ready() -> void:
	if %StateMachine and %StateMachine is PlayerStateMachine:
		player_controller = %StateMachine.player_controller

idle_state.gd:

extends PlayerState

var input_len : float = 0.0

func _on_idle_state_processing(delta: float) -> void:
	if player_controller.is_node_ready():
		var input_len = player_controller._input_dir.length()
		if (player_controller and (input_len > 0)):
			player_controller.state_chart.send_event("onMoving")

_on_idle_state_processing() is the signal from the Idle single state node and it calls every frame. Trouble is player_controller._input_dir.length() is always 0.0 in this scope, like a default value but not null, when it should be greater than 0 since its the WASD input (not normalised). Is there a better way to reference variables in a parent node or root node that I’m missing? Massive Godot noob here, still learning and hope my issue isn’t too badly worded.

var _input_dir declares a new variable, so you have two variables with the same name. The second one is only accessible inside the _physics_process() function and receives the input values.

To use the variable declared at the top, change it to:

	_input_dir = Input.get_vector("player_strafe_left", "player_strafe_right", "player_forward", "player_backward")

That fixed it straight away, thank you so much!