Custom object-creating function not being called

Godot Version

4.2.2 stable Windows 11

Question

I have this script extension hierarchy:
CharacterBody2D > enemy.gd > ai_fighter.gd > yellowslime.gd

In enemy.gd, I declare this function:

func CreateShotA1(bullet_type : String, colour : int, pos : Vector2, speed : float, accel : float, target_speed : float, angle : float, angular_velocity : float, lifespan : float, dmg : float):
	var objShot = load("res://Enemy/Bullets/" + bullet_type + ".tscn").instantiate()
	objShot.colour = colour
	objShot.global_position = pos
	objShot.speed = speed
	objShot.accel = accel
	objShot.target_speed = target_speed
	objShot.angle = angle
	objShot.angular_velocity = angular_velocity
	objShot.lifespan = lifespan
	objShot.damage = dmg
	return objShot
	print("shot created!")

And in yellowslime.gd, I have this code to call the function on death:

if hp <= 0 :
		CreateShotA1("ball_M", 0, global_position, 60, 0, 60, 90, 0, 3, 5)
                ###death code is after this

My ball_M scene uses the universal bullet script:

func _ready():
	$Sprite2D.set_frame(colour)
	if not lifespan == null:
		await get_tree().create_timer(lifespan).timeout
		queue_free()

func _physics_process(delta):
	speed = move_toward(speed, target_speed, accel)
	angle += angular_velocity
	velocity = Vector2.from_angle(angle) * speed
	move_and_slide()

In theory, this code should spawn a ball_M bullet on yellowslime’s death, at the same position as yellowslime, moving straight downwards at a constant speed, that doesn’t shift direction, and lasts for 3 seconds. However, nothing happens, and the output console doesn’t even print “shot created!”, indicating that either the CreateShotA1 function isn’t being called at all, or it is being called but the code is not running.

What am I doing wrong? Any help is appreciated.

Well you’re returning before you do the print(“shot created!”), so I wouldn’t expect that to ever print.

I also don’t see any code to add objShot as a child anywhere (maybe it was just cut off?)

i changed the order of return and print, and now at least it’s printing.

What do you suggest I add objShot as a child to? I tried just add_child but that didn’t work (probably because yellowslime is supposed to spawn this object on death), and I tried get_tree().get_root().add_child(objShot) but that didn’t seem to work either for some reason.

Great! Yeah returns will always exit a function, sometimes this can be really helpful.

yellowslime would probably make the most sense, or yellowslime’s parent.

I added get_parent().add_child(objShot) to the CreateShotA1 function, but still, nothing happens.
My scene tree looks like this:
World > EnemySpawner > enemy (extends to) yellowslime
In other words, yellowslime should be adding objShot as a child of EnemySpawner.

Sounds like add_sibling (or your get_parent.add_child rendition) should work, is there any more of that updated script you can share?

Tried that, and same thing.

My enemy.gd script currently looks like this:

extends CharacterBody2D

@export var hitboxradius = 10
@export var hurtboxarea = Vector2(10, 10)
@export var hp = 10
@export var damage = 1
@export var kb_recovery = 3.5
var kbspeed = 0
var kbdir = Vector2.ZERO
var totalkb = Vector2.ZERO
var is_dead = false

@onready var hitbox = $"Hitbox/Hitbox2"
@onready var iframes = $"iFrames"
@onready var hurtbox = $Hurtbox
@onready var collision = $"Hurtbox/Hurtbox2"
@onready var player = get_tree().get_first_node_in_group("player")

@onready var snd_hit = $enemy_hit
@onready var snd_crit = $critical_hit
@onready var hitflash_enabled = false

func _ready():
	hitbox.shape.set_radius(hitboxradius)
	collision.shape.size = hurtboxarea

func take_damage(dmg, knockback, is_critical) :
	$HitFlashAnimationPlayer.play("hitflash")
	hp -= dmg
	kbdir = player.global_position.direction_to(global_position)
	totalkb = kbdir * knockback
	if hp > 0:
		if is_critical :
			snd_crit.play()
		else:
			snd_hit.play()

func CreateShotA1(bullet_type : String, colour : int, pos : Vector2, speed : float, accel : float, target_speed : float, angle : float, angular_velocity : float, lifespan : float, dmg : float):
	var objShot = load("res://Enemy/Bullets/" + bullet_type + ".tscn").instantiate()
	add_sibling(objShot)
	objShot.colour = colour
	objShot.global_position = pos
	objShot.speed = speed
	objShot.accel = accel
	objShot.target_speed = target_speed
	objShot.angle = angle
	objShot.angular_velocity = angular_velocity
	objShot.lifespan = lifespan
	objShot.damage = dmg
	print("shot created!")
	return objShot

My ai_fighter.gd script looks like this:

extends "res://Enemy/enemy.gd"

@export var movement_speed = 15.0

func _physics_process(_delta):
	var direction = global_position.direction_to(player.global_position)
	totalkb = totalkb.move_toward(Vector2.ZERO, kb_recovery)
	velocity = direction*movement_speed
	velocity += totalkb
	move_and_slide()

And my yellowslime script looks like this:

extends "res://Enemy/AIs/ai_fighter.gd"

@onready var sprite = $Sprite2D
@onready var anim = $AnimationPlayer

func _ready():
	anim.play("walk")

func _process(delta):
		var direction = global_position.direction_to(player.global_position)
		if direction.x > 0.1:
			sprite.flip_h = true
		elif direction.x < -0.1:
			sprite.flip_h = false


func _on_animation_player_animation_finished(death_animation):
	queue_free()


func _on_hurtbox_hurtparent(dmg, knockback, is_critical):
	take_damage(dmg, knockback, is_critical)
	if hp <= 0 :
		CreateShotA1("ball_M", 0, global_position, 60, 0, 60, 90, 0, 3, 5)
		$Hurtbox.queue_free()
		$Hitbox.queue_free()
		$EnemyOnlyCollision.queue_free()
		$slime_death.set_pitch_scale(randf_range(0.9, 1.1))
		$slime_death.play()
		anim.play("death_animation")

You need to make an instance, then add it.

They do!


Does your bullet scene do any calculations on _ready()?

1 Like

What do you mean? My original post has the entire bullet script’s _ready() function. The only thing I didn’t post from my bullet script all the variables being prepared with @onready.

Yes apologies now I see ball_M in the first post.

Have you check the scene tree while running? The “remote” tab? If it’s printing it should also be adding the child successfully.

Keep in mind _ready() triggers immediately upon add_child/add_sibling, so you should set all of the properties before adding it. I can’t tell if that would cause issue, maybe lifespan is being defaulted to 0.0 seconds.

func CreateShotA1(bullet_type : String, colour : int, pos : Vector2, speed : float, accel : float, target_speed : float, angle : float, angular_velocity : float, lifespan : float, dmg : float):
	var objShot = load("res://Enemy/Bullets/" + bullet_type + ".tscn").instantiate()

	# modifying properties
	objShot.colour = colour
	objShot.global_position = pos
	objShot.speed = speed
	objShot.accel = accel
	objShot.target_speed = target_speed
	objShot.angle = angle
	objShot.angular_velocity = angular_velocity
	objShot.lifespan = lifespan
	objShot.damage = dmg

	# add to scene tree
	add_sibling(objShot)
	print("shot created!")
	return objShot
1 Like

Ha, guess i didn’t scroll over enough :smiley:

You’re not seeing the Z index, is it possible is creating behind another node so you just don’t see it?

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