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:
+23
-17
@@ -11,7 +11,6 @@ func build() -> void:
|
|||||||
_build_walls()
|
_build_walls()
|
||||||
_build_lighting()
|
_build_lighting()
|
||||||
_build_player()
|
_build_player()
|
||||||
_build_camera()
|
|
||||||
_build_ui()
|
_build_ui()
|
||||||
|
|
||||||
|
|
||||||
@@ -65,35 +64,42 @@ func _build_player() -> void:
|
|||||||
shape.shape.radius = 0.4
|
shape.shape.radius = 0.4
|
||||||
shape.shape.height = 1.8
|
shape.shape.height = 1.8
|
||||||
player.add_child(shape)
|
player.add_child(shape)
|
||||||
|
|
||||||
|
# State machine
|
||||||
var sm := Node.new()
|
var sm := Node.new()
|
||||||
sm.name = "MovementStateMachine"
|
sm.name = "MovementStateMachine"
|
||||||
player.add_child(sm)
|
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()
|
var st := Node.new()
|
||||||
st.name = "state_" + state_name
|
st.name = "state_" + state_name
|
||||||
sm.add_child(st)
|
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")
|
var mover_script = load("res://movement/player_movement_controller.gd")
|
||||||
if mover_script:
|
if mover_script:
|
||||||
player.set_script(mover_script)
|
player.set_script(mover_script)
|
||||||
# set_script after node is in tree does not auto-call _ready()
|
# set_script does not auto-call _ready(); do it manually
|
||||||
# Manually initialize the controller
|
|
||||||
if player.has_method("_ready"):
|
if player.has_method("_ready"):
|
||||||
player._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:
|
func _build_ui() -> void:
|
||||||
var canvas := CanvasLayer.new()
|
var canvas := CanvasLayer.new()
|
||||||
canvas.name = "UI"
|
canvas.name = "UI"
|
||||||
|
|||||||
Reference in New Issue
Block a user