Cannot call method 'get_node' on a null value

Godot Version

4.3.stable.mono

Question

`I have a code that should cancel action when pressing Z:

func _input(event):
	if event is InputEventKey and event.keycode == KEY_Z and event.pressed:
		if get_child_count() > 1:
			get_child(1).queue_free()`

but instead I have an error “Cannot call method ‘get_node’ on a null value” on the line “var targets = get_child(1).get_node("TowerDetector").get_overlapping_bodies()
This happens when I drag child (tower), then Press “Z”, It clears the tower from the view and exactly after I drop a tower this error occurs

FULL code:

extends Panel

@onready var tower = preload("res://Towers/RedBullet.tscn")
var currTile

func _input(event):
	if event is InputEventKey and event.keycode == KEY_Z and event.pressed:
		if get_child_count() > 1:
			get_child(1).queue_free()

func _on_gui_input(event):
	if Game.Gold >= 10:
		var tempTower = tower.instantiate()
		if event is InputEventMouseButton and event.button_mask == 1:
			
			add_child(tempTower)
			tempTower.global_position = event.global_position
			#tempTower.process_mode = Node.PROCESS_MODE_DISABLED
			
			tempTower.scale = Vector2(1,1) #area of a tower from panel
		elif event is InputEventMouseMotion and event.button_mask == 1:
			#button left down and dragging
			if get_child_count() > 1:
				
				get_child(1).global_position = event.global_position
				#Check if on Dirt Tile.
				var mapPath = get_tree().get_root().get_node("Main/TileMap")
				var tile = mapPath.local_to_map(get_global_mouse_position())
				currTile = mapPath.get_cell_atlas_coords(0, tile, false)
				var targets = get_child(1).get_node("TowerDetector").get_overlapping_bodies()
				if (currTile == Vector2i(4,5)):
					if (targets.size() > 1):
						get_child(1).get_node("Area").modulate = Color(255,255,255)
					else:
						get_child(1).get_node("Area").modulate = Color(0,255,0)
				else:
					
					get_child(1).get_node("Area").modulate = Color(255,255,255)
		
		elif event is InputEventMouseButton and event.button_mask == 0:
			#button left release
			if event.global_position.x >= 3340: #area where can't place towers
				if get_child_count() > 1:
					get_child(1).queue_free()
			
			else:
				#check for valid tile:
				if get_child_count() > 1:
					get_child(1).queue_free()
				if currTile == Vector2i(4,5):
					var targets = get_child(1).get_node("TowerDetector").get_overlapping_bodies() #this is where Error is
					var path = get_tree().get_root().get_node("Main/Towers")
					if (targets.size() < 2):
						path.add_child(tempTower)
						tempTower.global_position = event.global_position
						tempTower.get_node("Area").hide()
						Game.Gold -= 10
		else:
			if get_child_count() > 1:
				get_child(1).queue_free()

Please put all of the code you post here between three ticks, with “gd” behind the first set to improve highlighting:
```gd
# This is where you put code, “gd” makes strings and keywords in comments look good, for example.
```
Will look like this:

# This is where you put code, "gd" makes strings and keywords in comments look good, for example.

About the error:

The error is saying that the node you are trying to call get_node on is null, i.e. hasn’t been assigned a value. The node in question here is get_child(1), so for some reason, the second child of the script’s node doesn’t exist (there is only one child / no child at all).

There might only be one child is because in the line directly before you are destroying the second child, and there is no check in the first place if there are enough children to call get_child(1).

To fix this, you can check in the line before the error if there are at least two children:

# adding to the if-statement you already have
if get_child_count() > 1 and currTile == Vector2i(4, 5):

I don’t understand the point of destroying the second child there, and it seems to be duplicated from the section four lines further up. Maybe the underlying problem has to do with this, and you should remove that line or place it at the end of the block.

Instead of keycodes please read about input actions so you can allow players to redefine the key/buttons at a later point Player scene and input actions — Godot Engine (4.4) documentation in English
That will help you to move the code from _on_gui_input to the _input function where it belongs and you’ll have better control about what happens to your nodes and you can return early (return early is a popular software design pattern) before you hit potential problems.

1 Like

If that’s saying you can’t call get_node() on a null value, then get_child(1) is returning null.

I’d suggest something like this:

    var child = get_child(1)
    if !is_instance_valid(child):
        print("Second child isn't a valid instance!")
        return

    print("Second child is good, continuing...")

    var targets = child.get_node("TowerDetector").get_overlapping_bodies()

My suspicion is you’re going to see some crossed wires in your input logic where the delete gets fired immediately before the get_overlapping_bodies() or something.

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.