How do I get a working deathstate from an autoload?

Godot Version

4.2.2

Question

I want to kill the player. I have added necessary functionality for that, in the player.gd script:

signal player_died

...

const PLAYER_MAX_HEALTH:float = 100.0

...

var player_health = PLAYER_MAX_HEALTH

...

func _process(delta):
	if player_health == 0:
		die()

...

func die() -> void:
	player_died.emit()

Simple as, and this part of the code works fine (I’ve checked with print() at various spots, all turned out correct)

I have this autoload script, deathmanager.gd:

extends Node

var player_group = null

func _ready()->void:
	player_group = get_tree().get_first_node_in_group("Player")
	if player_group != null && player_group is Player:
		var player = player_group as Player
		player.player_died.connect(kill_player)

func kill_player()->void:
	print("yuo ded")

Yet it doesn’t work properly, I’ve checked and I definitely haven’t misspelled Player as a group. What mistake am I making? Is this even a feasibly good solution for player death?

Have you checked if the signal is connected?

func _ready()->void:
	player_group = get_tree().get_first_node_in_group("Player")
    print("Player: ", player_group)
	if player_group != null && player_group is Player:
		var player = player_group as Player
		player.player_died.connect(kill_player)
        print("Connected: ", player.player_died.is_connected(kill_player))

Tried it just now; nothing was printed. This prints nothing to console which confuses me more.

are you sure this is in autoload?

It wasn’t up to now. I am dumb.

We’ve circled back around though, because it prints this:

Player: <Object#null>

Is player in the first scene you start?

No, the scene starts in a main menu, from which I switch to the scene containing the player. How can I make it so that this can handle that issue?

The autoload will be before anything else is loaded

When autoloading a script, a Node will be created and the script will be attached to it. This node will be added to the root viewport before any other scenes are loaded.

— from Singletons (Autoload) docs

You will need to wait a frame for the player to be ready.

func _ready()->void:
	await get_tree().process_frame

	player_group = get_tree().get_first_node_in_group("Player")
	if player_group != null && player_group is Player:
		var player = player_group as Player
		player.player_died.connect(kill_player)
2 Likes

in your player_scene you can just do this:

func _ready():
    deathmanager.set_player(self)

and in the deathmanager.gd:

var player

func set_player(_player):
    player = _player
    player.player_died.connect(kill_player)
1 Like

Could you call the autoload’s function directly?

func _process(delta):
	if player_health == 0:
		die()

...

func die() -> void:
	DeathManager.kill_player()
2 Likes

Calling it directly works much easier compared to the insane workaround solution I was cooking up based off of the solutions proposed.

Thank you and herrspaten for your help :slight_smile: if I could mark multiple replies as solutions, I most likely would have.

1 Like

By the way to ensure possible bug, if you reduce the health under 0, you can check if player_health <= 0: instead of exact 0 value.

1 Like

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