!! Node not found, please help!! :(

Godot Version

v4.5.1.stable.steam [f62fdbde1]

Question

i have been working on my game that i want to release on itch as my first ever finished and released game, i have stumbled upon a bug in my game that wont let me update the visibility or the item in my ui, in my ui i have 3 buttons that let me build with randomly selected packed scenes.after the round ends the selected scenes reset and are able to be selected. once you run out of time or select a block the menu dissapears or visibility = false. ever since i moved my control node to a canvas layer my game manager cant seem to update it after the round ends. i tried to fix the bug by myself and tried to use chat gpt for assistance in fixing the bug, i think it made it worse and now i don’t know how to fix my code.

error, from main script

E 0:00:02:563 main_controller.gd:61 @ change_2d_scene(): Node not found: “CanvasLayer/Control” (relative to “/root/main/Node2D/Scene”).
<C++ Error> Method/function failed. Returning: nullptr
<C++ Source> scene/main/node.cpp:1907 @ get_node()
main_controller.gd:61 @ change_2d_scene()
main_controller.gd:24 @ _ready()

please help and thank you

scene heiarchy:

game controller scene:

node

-controll node

-node2d

-timer

-timer

-canvas layer

–label

–label

main game scene:

node2d

-player

-static body

-node2d(placement_controller)

-canvas layer

–controller node

___panel

_____button 1

____button 2

____button 3


scripts

main script:

extends Node
class_name GameController

@export var scene_2d :Node2D
@export var scene_ui :Control

@onready var round_timer: Timer = $Round_Timer
@onready var intermission_timer: Timer = $Intermission_timer

var selector_controller :Node = null

var current_disaster = Node

var current_round:int = 0
var round_active = false
var intermission_active = false

var current_2d
var current_ui

func _ready() → void:
Globals.game_controller = self
#current_ui = splashscreen here (for when you load it up)
Globals.game_controller.change_2d_scene(“res://scenes/crappy_world.tscn”)
start_round()

func _physics_process(delta: float) → void:

if round_active:
	$"CanvasLayer/round type".text = "round time"
	$CanvasLayer/time_left.text = format_time(round_timer.get_time_left())
 
if  intermission_active:
	$"CanvasLayer/round type".text = "intermission time"
	$CanvasLayer/time_left.text = format_time(intermission_timer.get_time_left())

func change_gui_scene(new_scene:String, delete:bool = true, keep_running:bool = false) → void:
if current_ui != null:
if delete:
current_ui.queue_free()#removes node
elif keep_running:
current_ui.visible = false# keeps running and in memory
else:
scene_ui.remove_child(current_ui) #stays in memory, dosent run
var new = load(new_scene).instantiate()
scene_ui.add_child(new)
current_ui = new

func change_2d_scene(new_scene:String, delete:bool = true, keep_running:bool = false) → void:
if current_2d != null:
if delete:
current_2d.queue_free()#removes node
elif keep_running:
current_2d.visible = false# keeps running and in memory
else:
scene_2d.remove_child(current_2d) #stays in memory, dosent run
var new = load(new_scene).instantiate()
scene_2d.add_child(new)
current_2d = new
selector_controller = current_2d.get_node(“CanvasLayer/Control”)
if new.has_node(“selector_controller”):
selector_controller = new.get_node(“selector_controller”)
else:
selector_controller = null

func format_time(t: float) → String:
var minutes = int(t) / 60
var seconds = int(t) % 60
return “%d:%02d” % [minutes, seconds]

func start_round():
current_round += 1
round_timer.start()
print(“round “,current_round,” has began”)
round_active = true
intermission_active = false
if selector_controller:
hide_selector_panel()

func end_round():
print(“round ended, intermission started”)
intermission_timer.start()
#clear disasters here
$CanvasLayer/time_left.set_text(str(intermission_timer.get_time_left()))
round_active = false
intermission_active = true
if selector_controller:
show_selector_panel()

func _on_round_timer_timeout() → void:
end_round()
if selector_controller:
selector_controller.randomize_choices()

func hide_selector_panel():
if selector_controller:
selector_controller.visible = false

func show_selector_panel():
if selector_controller:
selector_controller.visible = true

func _on_intermission_timer_timeout() → void:
start_round()

selector script:

extends Control

var selected_scene: PackedScene
var placement_controller: Node2D

var select_1:Array[PackedScene] = [
preload(“res://scenes/block_base.tscn”),
preload(“res://scenes/metal_block.tscn”),
preload(“res://scenes/straw_block.tscn”),
preload(“res://scenes/wood_block.tscn”)

]

var select_2:Array[PackedScene] = [
preload(“res://scenes/block_base.tscn”),
preload(“res://scenes/metal_block.tscn”),
preload(“res://scenes/straw_block.tscn”),
preload(“res://scenes/wood_block.tscn”)

]

var select_3:Array[PackedScene] = [
preload(“res://scenes/block_base.tscn”),
preload(“res://scenes/metal_block.tscn”),
preload(“res://scenes/straw_block.tscn”),
preload(“res://scenes/wood_block.tscn”)

]

func _ready() → void:
placement_controller = get_parent().get_parent().get_node(“placement_controller”)
randomize()
randomize_choices()
if placement_controller == null:
print(“Placement controller not found!”)

func randomize_choices():
select_1.shuffle()
select_2.shuffle()
select_3.shuffle()

$Panel/BoxContainer/option_1.texture_normal = get_scene_texture_1()
$Panel/BoxContainer/option_2.texture_normal = get_scene_texture_2()
$Panel/BoxContainer/option_3.texture_normal = get_scene_texture_3()

func _on_option_1_pressed() → void:
if placement_controller:
selected_scene = select_1[0]
placement_controller.current_placable = selected_scene
placement_controller.can_place = true
placement_controller.draw_ghost()
Globals.game_controller.hide_selector_panel()

func _on_option_2_pressed() → void:
if placement_controller:
selected_scene = select_2[0]
placement_controller.current_placable = selected_scene
placement_controller.can_place = true
placement_controller.draw_ghost()
Globals.game_controller.hide_selector_panel()

func _on_option_3_pressed() → void:
if placement_controller:
selected_scene = select_3[0]
placement_controller.current_placable = selected_scene
placement_controller.can_place = true
placement_controller.draw_ghost()
Globals.game_controller.hide_selector_panel()

func set_placement_controller(controller: Node2D) → void:
placement_controller = controller

func get_scene_texture_1() → Texture:
var temp_node_1 = select_1[0].instantiate()
var sprite = temp_node_1.get_node_or_null(“Sprite2D”)
var new_texture = null
if sprite:
new_texture = sprite.texture
temp_node_1.queue_free()
return new_texture

func get_scene_texture_2() → Texture:
var temp_node_2 = select_2[0].instantiate()
var sprite = temp_node_2.get_node_or_null(“Sprite2D”)
var new_texture = null
if sprite:
new_texture = sprite.texture
temp_node_2.queue_free()
return new_texture

func get_scene_texture_3() → Texture:
var temp_node_3 = select_3[0].instantiate()
var sprite = temp_node_3.get_node_or_null(“Sprite2D”)
var new_texture = null
if sprite:
new_texture = sprite.texture
temp_node_3.queue_free()
return new_texture

please help as i am a beginner gamedev and do not want to give up another project.

Please format your code properly, otherwise very few people will even bother to try and make sense of it.

2 Likes

Adding on to what @tibaverus said:

A screen shot of your scene tree is going to be much more useful than a text description. There are a lot of things we can tell from it from a glance that you might not notice.

1 Like