test: load MovementStateMachine + state scripts via set_script() at runtime

Root cause: builder created plain Node instances for the state machine
and states, so _machine.player = self in PlayerMovementController
crashed with 'Invalid assignment ... on base object of type Node'.
Now each node gets its real script attached before _ready() runs.
This commit is contained in:
2026-06-03 00:36:05 -04:00
parent 9bdbc69ddd
commit 1feefbf811
+23 -17
View File
@@ -11,7 +11,6 @@ func build() -> void:
_build_walls()
_build_lighting()
_build_player()
_build_camera()
_build_ui()
@@ -65,35 +64,42 @@ func _build_player() -> void:
shape.shape.radius = 0.4
shape.shape.height = 1.8
player.add_child(shape)
# State machine
var sm := Node.new()
sm.name = "MovementStateMachine"
player.add_child(sm)
for state_name in ["ground", "air", "wall_run", "wall_cling", "slide", "dash"]:
var sm_script = load("res://movement/movement_state_machine.gd")
if sm_script:
sm.set_script(sm_script)
# State children
var state_scripts := {
"ground": "res://movement/states/state_ground.gd",
"air": "res://movement/states/state_air.gd",
"wall_run": "res://movement/states/state_wall_run.gd",
"wall_cling": "res://movement/states/state_wall_cling.gd",
"slide": "res://movement/states/state_slide.gd",
"dash": "res://movement/states/state_dash.gd",
}
for state_name in state_scripts:
var st := Node.new()
st.name = "state_" + state_name
sm.add_child(st)
var st_script = load(state_scripts[state_name])
if st_script:
st.set_script(st_script)
# Movement controller
var mover_script = load("res://movement/player_movement_controller.gd")
if mover_script:
player.set_script(mover_script)
# set_script after node is in tree does not auto-call _ready()
# Manually initialize the controller
# set_script does not auto-call _ready(); do it manually
if player.has_method("_ready"):
player._ready()
func _build_camera() -> void:
var cam := Camera3D.new()
cam.name = "FpsCamera"
cam.current = true
cam.position = Vector3(0, 1.7, 0)
cam.fov = 90.0
var player_node = get_node_or_null("Player")
if player_node:
player_node.add_child(cam)
else:
add_child(cam)
func _build_ui() -> void:
var canvas := CanvasLayer.new()
canvas.name = "UI"