#Receiving health data from signal, but... I am not...

1 messages · Page 1 of 1 (latest)

digital flame
#

I must be missing something super obvious because I have checked and triple checked and am at a total loss.

What do I want to do?

I want to receive the health data inside of the resource_ui_health_ui_numbers node which is handled by the game_state_machine. The health data is handled by the stats node within the player scene.

How am I attempting to do this?

  1. PlayerStats (stats node's class) has a signal defined in the namespace and a function.
player_stats.gd

signal health_update(health: Array[int])

func send_health() -> void:
    var health_data: Array[int] = [player_stat_current_health, player_stat_max_health]
    print("Emitting health_update with data:", health_data)
    health_update.emit(health_data)
  1. PlayerState (player_state node's class) handles a cycle for the state of player variants. It first calls an update to health and then it calls the send_health function. The check_state_of_player function is connected to the timer timeout
player_state.gd

func check_state_of_player() -> void:
    var check_time_start: int = Time.get_ticks_msec()
    
    # Insert all player related updates to status, attributes, modifiers, etc in here.
    # \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/
    
    stats._validate_player_tnl()
    inventory_modifier_dictionary = item_modifiers.collect_modifiers_from_items(inventory_modifier_dictionary, item_modifiers.items_equipped)
    stats.update_health()
    stats.send_health()
    # /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\
    # Do not put anything below this for player updates to ensure tick timer remains functionally correct.
    var check_time_end: int = Time.get_ticks_msec()
    
    if not tick_time_changed == (check_time_end - check_time_start) * 3:
        print("Tick length to execute player check changed: {previous}:{equalifier}{change}".format({"previous" : tick_time_changed, "equalifier" : "+" if (tick_time_changed - (check_time_end - check_time_start)) >= 0 else "", "change" : (tick_time_changed - (check_time_end - check_time_start))}))
        tick_time_changed = check_time_end - check_time_start
  1. In the ui scene there the following logical functions to receive and process the health data into a RichTextLabel text.
class_name HealthNumbers extends RichTextLabel

func set_health_numbers(health_current: int, health_max: int) -> void:
    text = "[b]Health[/b]" + str(health_current) + " / " + str(health_max)

func update_health(health_numbers: Array[int]) -> void:
    print("update_health called")
    set_health_numbers(health_numbers[0], health_numbers[1])
  1. in another scene I have multiple of what I call "primary state machines" which handle the bulk of the way the game loads things in-out as well as cross interaction between different aspects such as actor variables and ui components in this case. I have a node game_state_machine that connects this to a reference of the player and ui components being used.
class_name GameStateMachine extends Node

@onready var area_state_machine: AreaStateMachine = $area_state_machine
@onready var actor_state_machine: ActorStateMachine = $actor_state_machine
@onready var item_state_machine: ItemStateMachine = $item_state_machine
@onready var ui_state_machine: UIStateMachine = $ui_state_machine

# References to Nodes for data passing purposes across state machines
var player_reference: Player
var health_ui_reference: HealthNumbers

func _ready() -> void:
    actor_state_machine.create_player()
    area_state_machine.spawn_debug_area()
    ui_state_machine.create_ui()
    player_reference = get_node("actor_state_machine/player")
    health_ui_reference = get_node("ui_state_machine/resource_ui/resource_ui_canvas_layer/resource_ui_health_ui_rect/resource_ui_health_ui_numbers")
    player_reference.player_stats.health_update.connect(health_ui_reference.update_health)
#

When I run the project, I see that print("Emitting health_update with data:", health_data) is called and the log shows it, but print("update_health called") is not being called at all. I confirmed through print statements that 1) player reference in game_state_machine is valid and references the player node, 2) ui reference is valid through the same. 3) that the signal is connecting the 2 together.

But I see no change in the RichTextLabel text, nor do I see the "update_health called" text in the log.

#

some pictures of the scenetree's and other relevant bits

untold hawk
#

If I'm not mistaken the issue is with the subscription. player_reference.player_stats.health_update.connect(health_ui_reference.update_health) instead of this it should be PlayerStats.health_update.connect assuming that the class name of player_stats is PlayerStats

digital flame
# untold hawk If I'm not mistaken the issue is with the subscription. `player_reference.player...

Ah! So... you were on the right track I think, that suggestion did not work as it results in Invalid access to property or key 'PlayerStats' on a base object of type 'CharacterBody2D (Player)'. because PlayerStats is not a part of the class Player it's a seperate class entirely that Player relies upon. But I think you threw me in a good direction - In this screenshot you can see that I have in RED the player stats node with a PlayerStats class attached to it - but then I also in YELLOW am creating a new one entirely seperate from the one in RED and am referencing that one. I am gonna play around with this and see if it's resulting in the problem

#

Yup! That was it 🙂

The issue was resolved by removing the yellow references and instead putting in @onready var player_stats: PlayerStats = $player_state/stats