Weird bug I cannot find a reason for. Engine bug?

Godot Version

Godot 4

Question

Hello fellow Godot users! I’ve been working on my game, I made it so that when a timer ends a “starter_attack” scene gets instantiated and positioned to the player position (it will seem weird and no-sense in the video I’m uploading but it is because i’m gonna make it so that it queue_free()s some istants after it spawned and then respawn, basically)

So everything was working fine until i noticed that if i go to the enemy sometime after the weapon spawned the enemy stops getting queue_free()d by the starter_attack.
While if I instantly go to the enemy it will despawn as it is supposed to.
I even placed an attack on the floor, and even that one stops working, the enemy just goes through it.

The code I am using on the starter_attack is

extends Node2D
@export var attack_resource: Resource

# Called when the node enters the scene tree for the first time.
func _ready() -> void:
	pass


# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta: float) -> void:
	pass


func _on_area_2d_body_entered(body: Node2D) -> void:
	if body.is_in_group("enemies"):
		body.health -= attack_resource.damage

Note: attack_resource it’s just

extends Resource
class_name weapon_resource

@export var damage: int = 5
@export var weapon_level: int = 1

It is not anything very useful for now.

The code i am using for the weapon spawn (and for the character as a whole):

extends CharacterBody2D


const SPEED = 200.0
const JUMP_VELOCITY = -400.0
@export var weapon1: PackedScene
var new_weapon


func _physics_process(delta: float) -> void:
	# Add the gravity.

	# Handle jump.

	# Get the input direction and handle the movement/deceleration.
	# As good practice, you should replace UI actions with custom gameplay actions.
	var direction_horizontal := Input.get_axis("ui_left", "ui_right")
	if direction_horizontal:
		velocity.x = direction_horizontal * SPEED
	else:
		velocity.x = move_toward(velocity.x, 0, SPEED)

	var direction_vertical := Input.get_axis("ui_up", "ui_down")
	if direction_vertical:
		velocity.y = direction_vertical * SPEED
	else:
		velocity.y = move_toward(velocity.y, 0, SPEED)

	move_and_slide()


func _on_timer_timeout() -> void:
	var weapon_pos = global_position + Vector2(30, 0) 
	new_weapon = weapon1.instantiate()
	add_child(new_weapon)
	new_weapon.global_position = weapon_pos

The enemy code:

extends CharacterBody2D
@onready var adventurer = get_node("/root/TestingFields/Starter_character")
@export var enemy_resource: Resource
var health
func _ready() -> void:
	health = 5


func _physics_process(delta: float) -> void:
	var direction = global_position.direction_to(adventurer.global_position)
	velocity = direction * 250.00
	move_and_slide()
	if (health == 0):
		queue_free()

Btw basically all assets are temporary (just saying even though it is irrelevant to the problem.

You’re checking if health is exactly zero, not less than or equal to zero, so negative numbers like -5 will not trigger the code. Two weapons on top of eachother will deal 10 damage and put the enemy at -5 health.

2 Likes

Thanks dude that fixed it.
As programmers we have to reason in thinking of every little outcome possible in our code. And I didn’t do that there. lol

Hey since I already made this post can I ask you another question?
I just realised a problem that I will have when I continue the development of the game.
I realised that I code that I made for the weapon spawning is specific to this character. Which as itself right now it’s not a problem as this weapon is the starting one of the character.
BUT for other characters and in general for obtaining other weapons I cannot put all the code inside of the character’s script, as I would have to do an enormous series of IF statements for whether the character has the weapon or not + each weapon’s code.
The only way I found is to put the each weapon’s code in its own specific custom resource and then somehow attach that resources to the character (maybe with another resource).
I have no idea. What do you think?

Why doesn’t the @export for weapon1 work? You can override that value for different characters

It does work fine but i actually have the code for the weapon’s spawn in the character scene:

extends CharacterBody2D


const SPEED = 200.0
const JUMP_VELOCITY = -400.0
@export var weapon1: PackedScene
var new_weapon


func _physics_process(delta: float) -> void:
	# Add the gravity.

	# Handle jump.

	# Get the input direction and handle the movement/deceleration.
	# As good practice, you should replace UI actions with custom gameplay actions.
	var direction_horizontal := Input.get_axis("ui_left", "ui_right")
	if direction_horizontal:
		velocity.x = direction_horizontal * SPEED
	else:
		velocity.x = move_toward(velocity.x, 0, SPEED)

	var direction_vertical := Input.get_axis("ui_up", "ui_down")
	if direction_vertical:
		velocity.y = direction_vertical * SPEED
	else:
		velocity.y = move_toward(velocity.y, 0, SPEED)

	move_and_slide()


func _on_timer_timeout() -> void:
	var weapon_pos = global_position + Vector2(30, 0) 
	new_weapon = weapon1.instantiate()
	add_child(new_weapon)
	new_weapon.global_position = weapon_pos

Even though i now realise that i could move it to the weapon1 resource and make an attack() function or something like that, then make another resource for some sort of inventory system for the characters, so they can have multiple weapons without having to code each weapon in each character’s script.

Sorry if I am not explaining myself or i am misunderstanding, english is not my first language.

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