Godot Version
4.2.1
Question
Hi all!
I had a little problem here with a script that makes an enemy on my game(simple 2d platformer) that walks, shoots some projectiles and possibly die if a condition is met. This enemy just walk from one point to another and shoot a projectile(that’s not important)
The problem I was facing is when on_dead() function was executed.
After that, in the physics process I got this error:
Invalid get index ‘flip_h’ (on base: ‘previously freed’).
I made a debug inside of on_dead() and I noticed that even after the queue free, the physics process still executing the lines inside of it. I know(I think) this is because all this will happen at the end of the frame.
But this problem was solved simply changing how I declare the first time this varable, and I dont understand exactly why.
In my first version i had the sprite 2d like this:
@export var sprite: Sprite2D
And then i just changed it for
@onready var sprite= $Sprite2D
And… All of this just happened after put this enemy scene inside of my level scene AND then make a copy(ctrl+D) of this enemy to use it later in the game(like 500px ahead to say something), If I decided to not copy and just drag from my filesystem window, worked fine.
Since every enemy scene is packed into a individual scene, is not supposed to be safe to make copies with ctrl+D inside of my level?
I hope i was enough clear, and I really sorry if I wasn’t.
This is the code I’m using now that is working.
extends CharacterBody2D
@export var speed:= 100.0
@export var health:= 100.0
@export var projectile: PackedScene
@export var death_scene: PackedScene
@export var health_component: HealthComponent
@onready var sprite = $Sprite2D
@onready var marker_2d_left = $Marker2DLeft
@onready var marker_2d_right = $Marker2DRight
@onready var projectile_container = $ProjectileContainer
@onready var missile_launcher = $MissileLauncher
@onready var timer = $Timer
var initial_position_left
var initial_position_right
var walk_right:= false
var walk_left:= false
#var activation_projectile_distance = 400
var target: Player
func _ready():
target = get_tree().get_first_node_in_group("player")
health_component.base_health = health
initial_position_left = marker_2d_left.global_position.x
initial_position_right = marker_2d_right.global_position.x
timer.timeout.connect(on_timeout)
health_component.dead.connect(on_dead)
func on_timeout():
if target != null:
var projectile_instance = projectile.instantiate()
projectile_container.add_child(projectile_instance)
projectile_instance.global_position = missile_launcher.global_position
projectile_instance.speed = 30
timer.wait_time = randi_range(4,6)
func _physics_process(delta):
if global_position.x >= initial_position_right or walk_left:
walk_left = true
sprite.flip_h = walk_right
walk_right = false
velocity.x = -speed
if global_position.x <= initial_position_left or walk_right:
walk_right = true
walk_left = false
sprite.flip_h = walk_right
velocity.x = speed
if velocity.y <= 0:
velocity.y += 200
move_and_slide()
func set_limits_right_left():
velocity.x = 0
func on_dead():
health_component.queue_free()
if death_scene != null:
print("dead walker")
var death_instance = death_scene.instantiate()
death_instance.global_position = global_position
if sprite.flip_h and sprite != null: #Invalid get index 'flip_h' (on base: 'previously freed').
death_instance.scale.x *= -1
get_tree().get_first_node_in_group("enemies").add_child(death_instance)
queue_free()