#resource reference issue - queue_free not deleting node
1 messages · Page 1 of 1 (latest)
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????
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?
that didn't help either
yeah probably best to get copied data out of a class rather than within, however, if that data is held within the class it would only be deleted along with the queu_fre
No overloading, I don't think I unset the loot controller either
let me try that
didn't help 😦
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
I've deduced that it's this that causes it to not free. If I remove argument from the signal and the other side of the code, then don't pass in the fish_clone argument, it works again
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
I figured duplicate() would mean fish_clone is a new reference
maybe I'm making too much of an assumption there
no... I'm also shooting in the dark XD
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
i mean... shallow copying could be part of the issue
try removing the null assignments and check?
It's bad form generally but for troubleshooting...
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)
?
yeah....
no difference
ok yeah I'm sending you down a wild goose chase.... crap
oh wtf
even just emitting a string causes it
resource reference issue - queue_free not deleting node
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?
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
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()?
it's not calling queue_free
lol wut
oh ffs
lmao please share lol
i didn't add the argument from the caught emit to the minigamecontroller
so i don't do the sam thing later on XD
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
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.
good luck with the game!
I'll need it!