Help with emitting a signal from an instantiated node

Godot Version

4.2

Question

I have been trying to setup signals being emitted from an instantiated scene (zombie) using the official documentation Using signals — Godot Engine (stable) documentation in English and I am not understanding some key logic of where the expected code snipit needs to live.

Here is what I am wanting to have happen:

  1. main_world.gd instantiates zombie.tscn
  2. zombie is shot or run over and emits zombie_killed signal
  3. hud.gd updates zombies_killed string

Previously I had non-instantiated zombies and this setup worked fine but it doesn’t work for instantiated zombies and I am unable to figure out how to hook it up.

I am sure it is very simple but I am at a loss. If I fix the error Identifier “_on_zombie_killed” not declared in the current scope. in the current code, that just will send the emit from the main_world hud and after I connected it that way it doesn’t work either.

Any help is greatly appreciated!

zombie.gd

extends CharacterBody3D

@export_group("Zombie Stats")
@export var movement_speed: float = 4.0
@export var Health = 1

@onready var movement_target = %Vehicle
@onready var navigation_agent: NavigationAgent3D = get_node("NavigationAgent3D")
@onready var sfx_zombie_run_over = $"../sfx_zombie_run_over"
@onready var zombies_killed_label = get_node("hud/Score/Zombies_Killed/zombies_killed_label")

signal zombie_killed

func _ready() -> void:
    navigation_agent.velocity_computed.connect(Callable(_on_velocity_computed))

func set_movement_target(movement_target: Vector3):
	navigation_agent.set_target_position(movement_target)

func _physics_process(delta):
	if navigation_agent.is_navigation_finished():
		return

	var next_path_position: Vector3 = navigation_agent.get_next_path_position()
	var new_velocity: Vector3 = global_position.direction_to(next_path_position) * movement_speed
	if navigation_agent.avoidance_enabled:
		navigation_agent.velocity = new_velocity
	else:
		_on_velocity_computed(new_velocity)

func _on_velocity_computed(safe_velocity: Vector3):
	velocity = safe_velocity
	move_and_slide()

## Bullet damage logic
func Hit_Successful(Damage, _Direction: Vector3 = Vector3.ZERO, _Position: Vector3 = Vector3.ZERO):
	Health -= Damage
	if Health <= 0:
		zombie_killed.emit()
		queue_free()
		print("zombie shot")
		
## Collision damage logic
func _on_body_entered() -> void:
	zombie_killed.emit()
	$"../sfx_zombie_run_over".play()
	queue_free()
	print("zombie ran over")

main_world.gd

extends Node3D

@export var mob_scene: PackedScene

func _ready():
	var hud = get_node("hud")
	hud.zombie_killed.connect(_on_zombie_killed)

func _on_mob_timer_timeout():
	# Create a new instance of the Mob scene.
	var mob = mob_scene.instantiate()

	# Choose a random location on the SpawnPath.
	# We store the reference to the SpawnLocation node.
	var mob_spawn_location = get_node("ZombieSpawnPath/ZombieSpawnLocation")
	# And give it a random offset.
	mob_spawn_location.progress_ratio = randf()

	var player_position = $Vehicle.position
	mob.initialize(mob_spawn_location.position, player_position)


	# Spawn the mob by adding it to the Main scene.
	add_child(mob)

hud.gd

extends CanvasLayer

var zombies_killed = 0

func _ready():
	$Score/Zombies_Killed/zombies_killed_label.text = str(zombies_killed)


func _on_zombie_killed():
	zombies_killed = zombies_killed + 1
	$Score/Zombies_Killed/zombies_killed_label.text = str(zombies_killed)

after add_child, connect/listen the zombie_killed signal from zombie.gd
by adding this line:

mob.zombie_killed.connect(hud_increase_zombie_killing_count_method)

then also in your main_world.gd, write the func hud_increase_zombie_killing_count_method(): method

something like

func hud_increase_zombie_killing_count_method():
	$hud._on_zombie_killed()
1 Like

Thank you so much! If you are willing to help me with a nav issue as well I’d really appreciate it! Enemies path to position off NavRegion and not to set target - #9 by BrickyT

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