I’ve been working on a game where there’s a large enemy that summons rockets that hunt down the player. The problem is the player can’t kill them when the code to queue_free() the node clearly runs and every relevant detail is the same as a enemy that can be freed.
This is the rocket that can’t be freed:
extends CharacterBody3D
var speed = 10
var falldistance = 20
func _process(_delta: float) -> void:
var direction := gamemanager.player.global_position - global_position
var new_basis := Basis.looking_at(direction)
basis = basis.slerp(new_basis, 0.08)
velocity = -transform.basis.z * speed
hurt()
move_and_slide()
func _on_detect_ground_body_entered(_body: Node3D) -> void:
queue_free()
func get_fall_distance():
return falldistance
func hurt():
if gamemanager.player.p_range.get_collider()==self && gamemanager.player.animation_player.current_animation=="slice":
if gamemanager.player.airtime>get_fall_distance():
gamemanager.player.velocity.y = gamemanager.player.slamLaunchStr
queue_free()
func _on_timer_timeout() -> void:
self.queue_free()
And this is the enemy that spawns it and can be freed
extends CharacterBody3D
var speed = 4
@onready var player = gamemanager.player
enum states{ target, attack, sleep, rockets}
var CurrentState: states
var playerPosxy:Vector3
var falldistance = 40
var target: Vector3
var gravity = 1
var cooldown = false
var rockets = preload("res://scenes/projectiles/enemy/rocket.tscn")
var particle = preload("res://scenes/enemies/particle/golem_attack_particle.tscn")
@onready var startingPos = position
func _ready() -> void:
CurrentState = states.target
func _process(_delta: float) -> void:
playerPosxy = Vector3(player.position.x, position.y, player.position.z)
match CurrentState:
states.target:
target = playerPosxy
targeting()
states.attack:
attack()
states.rockets:
rocket()
grav()
hurt()
move_and_slide()
func attack():
if !cooldown:
$"attack range/CollisionShape3D".disabled = false
$cooldown.start()
cooldown = true
await get_tree().create_timer(0.2).timeout
$"attack range/CollisionShape3D".disabled = true
CurrentState = states.target
func rocket():
for i in range(4):
var rocketsInstatiate: Node3D = rockets.instantiate()
rocketsInstatiate.position = position
get_parent().get_parent().add_child(rocketsInstatiate)
CurrentState = states.target
func grav():
velocity.y -= gravity
func get_fall_distance():
return falldistance
func targeting():
look_at(target)
var targetVec: Vector3 = target - position
velocity = lerp(velocity, targetVec.normalized() * speed, 0.05)
if position.distance_to(player.position) < 4:
CurrentState = states.attack
func hurt():
if player.p_range.get_collider() == self && player.animation_player.current_animation == "slice":
if player.airtime>get_fall_distance():
player.velocity.y = player.slamLaunchStr
die()
func die():
queue_free()
func _on_timer_timeout() -> void:
if position.distance_to(player.position) > 20 && CurrentState == states.target:
CurrentState = states.rockets
$Timer.start(randf_range(2, 5))
func _on_cooldown_timeout() -> void:
cooldown = false
func _on_attack_range_body_entered(_body: Node3D) -> void:
if !player.iFrames:
var kbVec : Vector3 = (player.position - position).normalized()
player.velocity += kbVec * 25
player.velocity.y += 20
var particleInst: Node3D = particle.instantiate()
particleInst.global_transform = $"attack range/CollisionShape3D".global_transform
get_parent().add_child(particleInst)
The collision layers that matter towards the player raycast are the same and in both instances the launching the player does run, the rocket just can’t be freed in the rocket’s case. With the rocket it also doesn’t work if I have it queue free a collision shape in there or hide it’s mesh