#resource reference issue - queue_free not deleting node

1 messages · Page 1 of 1 (latest)

fierce seal
#

Copy pasting the start of my post from the quick help channel:

#

I'm making a game that has a fishing mechanic like Stardew Valley, which is working fine. I'm now trying to implement an inventory system so that when the player catches a fish it is added to their inventory.

The current flow goes like this:
The player clicks on a water tile
The player controller handles animation for casting the rod, and does some timer stuff to imitate waiting for a bite and showing a hit indicator when there is one
When the player responds to the bite, it spawns a separate scene which is the actual fishing minigame (this is exactly like stardew, click to move the bar, keep the fish in the bar)
A timer tracks a progress bar, and when complete (or empty and the fish was lost), emits a signal that indicates which state happened
Responding to that signal I have some code which calls queue_free() on the minigame scene, and it removes the scenes from the UI

Now I've added some more code to handle generating a fish (which is a custom Resource) via loot tables and some other fancy stuff, but the idea is the FishingMinigame scene creates an instance of a FishData Resource, and then the 'success' signal sends that resource out, where I'm then taking that resource and putting it into the player inventory (another resource)

But when I do that, the minigame doesn't disappear from the screen anymore... I'm assuming this is because there's some sort of reference to something which means queue_free never runs because it's not.... free? I've tried doing .duplicate() on the resource thinking that might lose the reference within the minigame, but no dice.... does anyone have any idea what I'm missing?

#

@steep cradle I've moved here 🙂

#

I've done a quick diagram to hopefully explain the general setup

#

I've omitted the loot table stuff, I'm fairly sure that's irrelevant

#

So I first spawn the minigame by firing a signal:

SignalBus.spawn_minigame.emit(SignalBus.Minigame.Fishing, player.global_position + Vector2(30, 0))
#

that's connected to this function in the MinigameController

func spawn_fishing_game(position: Vector2):
  fishing_minigame = preload("res://scenes/minigames/fishing/FishingMinigame.tscn").instantiate()
  fishing_minigame.loot_controller = fish_loot_controller

  if (position):
    fishing_minigame.position = position

  add_child(fishing_minigame)
#

The FishingMinigame scene does this:

func _ready() -> void:
  target_fish = loot_controller.generate_one_loot()
#

Then once the player has succesfully caught a fish, this runs:

func caught_fish():
  get_node("Fish").destroy()
  print_debug("Fish caught!")
  progress_bar.value = 0
  fishable = true
  var fish_clone = target_fish.duplicate()
  target_fish = null
  SignalBus.fish_minigame_caught.emit(fish_clone)
#

And that caught signal at the end is wired to this on the PlayerFishingController:

func on_fish_caught(fish: FishItem):
  is_reeling_in = false
  has_cast = false
  cleanup_bobber()
  cleanup_indicator()
  print_debug("caught a fish!" + fish.get_length_string())

  var slot_data = SlotData.new()
  slot_data.item_data = fish
  slot_data.quantity = 1
  player.inventory_data.pickup_slot_data(slot_data)

  SignalBus.enable_tile_selection.emit()

that "caught a fish" debug line prints "0cm", so the randomization that happened in the generate_one_loot function either isn't working, or is lost at some point

#

pickup_slot_data does this:

func pickup_slot_data(slot_data: SlotData) -> bool:
  for index in slot_datas.size():
    if !slot_datas[index]:
      slot_datas[index] = slot_data
      inventory_updated.emit(self)
      return true

  return false;
#

just attempting to add it to the first available slot in the hotbar (this works)

#

Wait, maybe I should be duplicating in the on_fish_caught side, not in the minigame side????

steep cradle
#

For honesty here, I'm definitely out of my wheelhouse here. However, I see that you assign the loot controller, does your code either unassign that to null or have you overloaded the =operator for that class?

steep cradle
fierce seal
#

let me try that

#

didn't help 😦

steep cradle
#

Anything that gets that kind of assignment of something outside the class needs to be unassigned before a queue_free as the class can't delete the data from other classes... in any case. hrmm

#

but that's clearly not your issue

fierce seal
#

it's not clearing if you lose, either

#

which doesn't pass any resource out

fierce seal
steep cradle
#
  var fish_clone = target_fish.duplicate()
  target_fish = null
  SignalBus.fish_minigame_caught.emit(fish_clone)

yeah i think since this class doesn't have an overloaded = as a copy constructor you're passing by reference so when you set it equal to null you're deleting the data you're attempting to send through the signal emit

fierce seal
#

I figured duplicate() would mean fish_clone is a new reference

#

maybe I'm making too much of an assumption there

steep cradle
#

no... I'm also shooting in the dark XD

fierce seal
#

but it's weird.....

This stops the scene being removed


  var fish_clone := target_fish.duplicate()
  target_fish = null
  loot_controller = null
  SignalBus.fish_minigame_caught.emit(fish_clone)

this causes the scene to be removed:


  var fish_clone := target_fish.duplicate()
  target_fish = null
  loot_controller = null
  SignalBus.fish_minigame_caught.emit()
#

nothing connected to that signal is even using the argument

#

maybe I need to move the "randomization" bit to the receiver and just emit the fish ID, look it up again

#

seems weird, but that must work

steep cradle
#

i mean... shallow copying could be part of the issue

fierce seal
#

oh........ 🤔

#

passing true in didn't fix it either

steep cradle
#

try removing the null assignments and check?

#

It's bad form generally but for troubleshooting...

fierce seal
#

how do you mean sorry

#
  var fish_clone := target_fish.duplicate(true)
  # target_fish = null
  # loot_controller = null
  SignalBus.fish_minigame_caught.emit(fish_clone)

?

steep cradle
#

yeah....

fierce seal
#

no difference

steep cradle
#

ok yeah I'm sending you down a wild goose chase.... crap

fierce seal
#

oh wtf

#

even just emitting a string causes it

#

resource reference issue - queue_free not deleting node

steep cradle
#

I mean you said that you're hitting the queue_free line in both cases so... what could be causing tha to fail?

#

could you have something that's calling data in any way from the scene?

fierce seal
#
func cleanup_fish_minigame():
  if (fishing_minigame):
    print_debug("calling queue_free on fishing minigame scene")
    fishing_minigame.queue_free()
    print_debug("fishing_minigame is_queued_for_deletion: ", fishing_minigame.is_queued_for_deletion())
    fishing_minigame = null

So I've just put this in

#

without emitting any data

#

oh wait lmfao

steep cradle
#

So it seems like there's a call to the node that's waiting for other calls to go ahead of it. Would it hurt to just use .free()?

fierce seal
#

it's not calling queue_free

steep cradle
#

lol wut

fierce seal
#

oh ffs

steep cradle
#

lmao please share lol

fierce seal
#

i didn't add the argument from the caught emit to the minigamecontroller

steep cradle
#

so i don't do the sam thing later on XD

fierce seal
#
func _ready() -> void:
  SignalBus.connect("fish_minigame_caught", self.cleanup_fish_minigame)

func cleanup_fish_minigame():
  print_debug("called cleanup_fish_minigame()");
  if (fishing_minigame):
    print_debug("calling queue_free on fishing minigame scene")
    fishing_minigame.queue_free()
    print_debug("fishing_minigame is_queued_for_deletion: ", fishing_minigame.is_queued_for_deletion())
    fishing_minigame = null
#

so it's never calling that function

#

let me just confirm adding the argument actually fixes it

#

yep

#

wtf godot

#

just silently doesn't call the method if the arguments mismatch I guess? ???

#

aaaaaaaand it's not even silent, there is a red error in my debugger 🤦‍♂️

how did I miss that

#

I'm so sorry

#

i've been working for too long and my brain is mush clearly

steep cradle
#

no worries! Good learning experience. I've been there too many times to count XD

#

hopefully i didn't just lead you offtrack and just talking helped.

fierce seal
#

yeah, rubber ducking is underrated!

#

thanks for the help, really appreciated!!

steep cradle
#

good luck with the game!

fierce seal
#

I'll need it!