Godot Version
4.6.2
Question
So i am trying to get an enemy spawner working, but when two enemies spawn at the same point they start vibrating then shoot offscreen. how would i fix this?
extends CharacterBody2D
@export var spawn_position = Vector2(-26, -79)
var respawn_pos: Array = [
Vector2(-26, -79),
Vector2(0, -79),
Vector2(41, -79)
]
#@export var enemy_id: int
@export var respawn_time := 3.0
@onready var sprite: Sprite2D = $Sprite2D
@onready var collision_shape: CollisionShape2D = $CollisionShape2D
@onready var timer: Timer = $Timer
var just_spawned := true
var invulnerable := false
var is_dead = false
var can_attack := true
var healing = false
var heal_cooldown = true
var health
var hit_cooldown = false
var original_layer: int
var original_mask: int
var speed = speedy
func _ready():
original_layer = collision_layer
original_mask = collision_mask
door = get_tree().get_first_node_in_group("door")
just_spawned = true
#sets spawn location
if GameState.on_main_menu:
GameState.enemy_2_positions = position
#if not is_dead:
#if not GameState.is_game_starting2:
#global_position = GameState.enemy_2_positions
#if GameState.is_game_starting2:
#global_position = spawn_position
#GameState.is_game_starting2 = false
move_and_slide()
func _deferred_restore():
await _wait_for_enemies()
restore_game_state()
func restore_game_state():
if not GameState.has_saved_state:
return
for enemy in get_tree().get_nodes_in_group("enemies"):
var id = enemy.get_instance_id()
if id in GameState.enemy_2_positions:
enemy.global_position = GameState.enemy_2_positions[id]
func disable_target():
# Turn OFF target
if is_dead or invulnerable:
return
GameState.money += 1
GameState.kills += 1
is_dead = true
sprite.visible = false
set_physics_process(false)
collision_shape.set_deferred("disabled", true)
await get_tree().physics_frame
timer.start(respawn_time)
func _on_timer_timeout():
can_attack = true
if is_dead:
var respawn_position = respawn_pos.pick_random()
global_position = respawn_position
# Restore collision settings
collision_layer = original_layer
collision_mask = original_mask
# Reactivate visuals
sprite.visible = true
invulnerable = true
# Re‑enable collision SAFELY
await get_tree().physics_frame
collision_shape.set_deferred("disabled", false)
set_physics_process(true)
is_dead = false
await get_tree().create_timer(0.3).timeout
invulnerable = false
#heals door when not getting hit
if not heal_cooldown:
if door and global_position.distance_to(door.global_position) > 20:
Global.health += 1
if Global.health > 100:
Global.health = 100
else:
heal_cooldown = true
@export var speedy: float = 100.0
var door: Node2D
@warning_ignore("unused_parameter")
func _physics_process(_delta):
if door == null:
return
# Direction toward door
var direction = (door.global_position - global_position).normalized()
# Move enemy
velocity = direction * speed
move_and_slide()
if sprite.visible == false:
speed = 0
if sprite.visible == true:
speed = speedy
GameState.enemy_2_positions = position
# enemy detects and attacks the door
if door and global_position.distance_to(door.global_position) < 20:
if can_attack:
attack_door()
Global.getting_hit = false
# enemy damages the door
func attack_door():
heal_cooldown = true
Global.health -= 1
#print("hit")
can_attack = false
timer.start(1.5) # attack cooldown time
if Global.health <= 0:
get_tree().change_scene_to_file("res://scenes/game_over.tscn")
func _wait_for_enemies():
while get_tree().get_nodes_in_group("enemies").is_empty():
@warning_ignore("redundant_await")
await get
Below is my script for the enemy spawner
extends Node2D
@export var enemy_scene: PackedScene
@export var enemy_count: int = 3
@export var spawn_positions := [
Vector2(-26, -79),
Vector2(0, -79),
Vector2(41, -79)
]
func _ready():
for i in range(enemy_count):
spawn_enemy()
func spawn_enemy():
var enemy = enemy_scene.instantiate()
enemy.global_position = get_random_spawn_pos()
add_child(enemy)
func get_random_spawn_pos() → Vector2:
var positions = [
Vector2(-26, -79),
Vector2(0, -79),
Vector2(41, -79)
]
return positions.pick_random()