Godot Version
Godot 4.0
Question
Hello, I was following this tutorial: https://www.youtube.com/watch?v=mum_l7HY4yE&t=4201s to make my own invader-esque game. I have coded the spawner so that every time all of the invaders die in a round the game spawns in more invaders until the player loses but i ran into a problem where after a certain amount of time, when all of the invaders have died the spawner just disappears and doesn’t spawn in more invaders resulting in this error: Invalid assignment of property or key ‘global_position’ with value of type ‘Nil’ on a base object of type ‘Area2D (ZombieShot)’. This is the script for the invader spawner:
invader_spawner.gd:
extends Node2D
class_name InvaderSpawner
signal invader_destroyed(points: int)
#signal game_won
signal game_lost
#reset number of rows every 5 rounds
var ROWS = 4
var COLUMNS = 11
const HORIZONTAL_SPACING = 32
const VERTICAL_SPACING = 32
const INVADER_HEIGHT = 24
const START_Y_POSITION = -50
const INVADERS_POSITION_X_INCREMENT = 10
const INVADERS_POSITION_Y_INCREENT = 20
var movement_direction = 1
var enemy_scene = preload("res://enemy.tscn")
var zombie_shot_scene = preload("res://invader_shot.tscn")
var zom_pos = null
var shootvar
var MyArray = []
var num_rounds = 1
var invader_destroyed_count = 0
var invader_total_count = ROWS * COLUMNS
@onready var movement_timer = $MovementTimer
@onready var zombie_shot = $Zombie_Shoot
@onready var invader_spawner = $"."
func _ready():
movement_timer.timeout.connect(move_invaders)
var invader_1_res = preload("res://Resources/invader_1.tres")
var invader_2_res = preload("res://Resources/invader_2.tres")
var invader_3_res = preload("res://Resources/invader_3.tres")
zombie_shot.timeout.connect(on_invader_shot)
var invader_config
count_invader(invader_1_res, invader_2_res, invader_3_res, invader_config)
func count_invader(res_1, res_2, res_3, conf):
print("count called")
for row in ROWS:
if row == 0:
conf = res_1 #add more zombies every time they get decimated
elif row == 1 || row == 2:
conf = res_2
elif row == 3 || row == 4:
conf = res_3
var row_width = (COLUMNS * conf.width * 3) + ((COLUMNS - 1) * HORIZONTAL_SPACING)
var start_x = (position.x - row_width) / 2
for col in COLUMNS:
var x = start_x + (col * conf.width * 3) + (col * HORIZONTAL_SPACING)
var y = START_Y_POSITION + (row * INVADER_HEIGHT) + (row * VERTICAL_SPACING)
var spawn_position = Vector2(x, y)
set_zombie_position(spawn_position)
spawn_invader(conf, spawn_position)
func PickRandom():
var arr_random = MyArray.pick_random()
if (is_instance_valid(arr_random)):
return arr_random
else:
return
func spawn_invader(invader_config, spawn_position: Vector2):
var invader = enemy_scene.instantiate() as Enemy
invader.config = invader_config
invader.global_position = spawn_position
invader.invader_destroyed.connect(on_invader_destroyed)
add_child(invader)
func set_zombie_position(zom_position: Vector2):
zom_pos = zom_position
func move_invaders():
position.x += INVADERS_POSITION_X_INCREMENT * movement_direction
func _on_left_wall_area_entered(area: Area2D) -> void:
if (movement_direction == -1):
position.y += INVADERS_POSITION_Y_INCREENT
movement_direction *= -1
func _on_right_wall_area_entered(area: Area2D) -> void:
if (movement_direction == 1):
position.y += INVADERS_POSITION_Y_INCREENT
movement_direction *= -1
func on_invader_shot():
var zombie_shot = zombie_shot_scene.instantiate() as ZombieShot
var random_child_position = get_children().filter(func (child): return child is Enemy).map(func (invader): return invader.global_position).pick_random()
#if (PickRandom() == null):
#return
#else:
get_tree().root.call_deferred("add_child", zombie_shot)
zombie_shot.global_position = random_child_position
#(364, 94)
#if is_instance_valid(zombie_shot):
#zombie_shot.global_position = random_child_position
#else:
#get_tree().root.add_child(zombie_shot)
#zombie_shot.global_position = random_child_position
func _process(delta: float) -> void:
var invader_1_res = preload("res://Resources/invader_1.tres")
var invader_2_res = preload("res://Resources/invader_2.tres")
var invader_3_res = preload("res://Resources/invader_3.tres")
var invader_config
if invader_destroyed_count == invader_total_count:
print("invader destroyed: " + str(invader_destroyed_count))
print("invader total: " + str(invader_total_count))
invader_destroyed_count = 0
num_rounds += 1
ROWS += 0.5
if num_rounds == 5:
num_rounds = 0
ROWS = 5
invader_spawner.global_position = Vector2(364, 94)
count_invader(invader_1_res, invader_2_res, invader_3_res, invader_config)
func on_invader_destroyed(points: int):
invader_destroyed.emit(points)
#invader_destroyed_count += 1
func _on_bottom_wall_area_entered(area: Area2D) -> void:
if "Enemy" in area.name:
game_lost.emit()
movement_timer.stop()
movement_direction = 0
I have rewatched the tutorial and rechecked all the scripts in my game but i don’t think i see any line that deletes the spawner anywhere