Update function not available. Need another to take it's place

Godot Version

Godot 4.4.1

Question

Hello again. I have a question… I’ve been trying to make an Inventory UI following a tutorial, so far, everything’s been doing well, making it open and close, and pause the game, etc. But this part here has been a problem:

 func _update():
 	for i in range(min(inventory.slots.size(), slots.size())):
 		slots[i].*update*(inventory.slots[i])

That “update(inventory.slots[i])” part leaves the error message:

Invalid type in function ‘update’ in base ‘Panel (slot_ui.gd)’. The Object-derived class of argument 1 (Resource (InventoryItem)) is not a subclass of the expected argument class.

This Godot version, unlike the tutorial’s, no longer has the “update” function. What could I do instead?

extends Control
 
signal opened
signal closed

var isopen: bool = false 

@onready var inventory: Inventory = preload("res://inventory/playerInventory.tres")
@onready var slots: Array = $NinePatchRect/GridContainer.get_children()

func _ready():
	inventory.updated.connect(_update)
 	_update()
 
func _update():
	for i in range(min(inventory.slots.size(), slots.size())):
		slots[i].update(inventory.slots[i])

func open():
	visible = true
	isopen = true
	opened.emit()

func close():
	visible = false
	isopen = false
	closed.emit()

How did you define your update function in the grid container’s children?

Please pardon my ignorance, but I don’t know exactly.

Here’s the code for slot_gui.gd, if it’s any help.

extends Panel
 
@onready var backgroundSprite: Sprite2D = $background
@onready var itemSprite: Sprite2D = $CenterContainer/Panel/item

func update(slot: InventorySlot):
 	if !slot.item:
		backgroundSprite.frame = 2
		itemSprite.visible = false
	else: 
		backgroundSprite.frame = 0
		itemSprite.visible = true
		itemSprite.texture = slot.item.texture
1 Like

your function takes a InventorySlot but your are giving it an object that is a InventoryItem; I’m not sure what is inside your inventory.slots array, maybe the resource is incorrect? What script does the playerInventory.tres have?

This is the script connected to playerInventory.tres:

extends Resource

class_name Inventory

signal updated

@export var slots: Array[InventoryItem]

func insert(item: InventoryItem):
	for slot in slots:
		if slot.item == item:
			slot.amount += 1
			updated.emit()
			return
	
	for i in range(slots.size()):
		if !slots[i].item:
			slots[i].item = item
			slots[i].amount = 1
			updated.emit
			return
1 Like

Hey, you are so close to posting correctly.
Instead of hitting the quote button (that looks like a ") hit the code button (it looks like this </> and tool tips ‘preformatted text’).
By the way you can edit your previous posts to update the code using the </> to fix the posted code.

1 Like

Not sure what you’d replace it with, doesn’t seem like this Inventory object has a InventorySlot object inside it. I don’t know what you would do to resolve this, maybe comb through your tutorial again.

1 Like

So sorry, will do.

1 Like

FWIW I tried changing the “(slot: InventorySlot)” in slot_gui.gd for “(slot: InventoryItem)” and it no longer crashes here, but on “if slot.item:” instead, giving the message:

Invalid access to property or key ‘item’ on a base object of type ‘Resource (InventoryItem)’.

func update(slot: InventoryItem):
>>>	if !slot.item:
		backgroundSprite.frame = 2
		itemSprite.visible = false

Yeah I’d figure you do want an InventorySlot, as the rest of the code expects that type. I’m just not sure where you would get an InventorySlot object from all the code posted

Alright, I’ve combed through the tutorial and the issue keeps being

Invalid access to property or key ‘item’ on a base object of type ‘Nil’.

Specifically on slot_gui.gd here:

extends Panel

@onready var backgroundSprite: Sprite2D = $background
@onready var itemSprite: Sprite2D = $CenterContainer/Panel/item

func update(slot: InventorySlot):
>>	if !slot.item:    
		backgroundSprite.frame = 2
		itemSprite.visible = false
	else: 
		backgroundSprite.frame = 0
		itemSprite.visible = true
		itemSprite.texture = slot.item.texture

At if !slot.item:

And at inventory_gui.gd here:

extends Control

signal opened
signal closed

var isOpen: bool = false 

@onready var inventory: Inventory = preload("res://inventory/playerInventory.tres")
@onready var slots: Array = $NinePatchRect/GridContainer.get_children()

func _ready():
	inventory.updated.connect(update)
	update()

func update():
	for i in range(min(inventory.slots.size(), slots.size())):
		slots[i].update(inventory.slots[i])

func open():
	visible = true
	isOpen = true
	opened.emit()

func close():
	visible = false
	isOpen = false
	closed.emit()

At both instances of update().

Is this clearer? (Sorry if it’s not.)

Maybe one of your inventory.slots is null or <empty> as it may show in the inspector.

In the Variables section, “slot” does indeed have <null> on it. It seems to be the source of the problem.

What could be done, then?

I have no idea what that data should be filled with, it sounds like it shouldn’t be empty/null as it’s named InventorySlot rather than say an Item. I don’t know how any of your InventorySlot nor InventoryItems are defined, but maybe your Inventory’s var slots should be an array of InventorySlot instead? And filled in within the editor?

The slots comes from

@onready var slots: Array = $NinePatchRect/GridContainer.get_children()

The NinePatchRect/GridContainer comes from the inventory_gui, the Inventory screen which appears on the… screen.

Alright, I solved it. Turns out, “slot” was <null>, right?

Well, the InventorySlot script was used for playerInventory.tres, which itself was used for the slots in the Inventory. However, the ‘slots’, accesible through the Inspector, supposed to be filled with the InventorySlot, were <empty> instead, so it just came out as an error.

Once I put InventorySlot in the designated spaces in the inspector, it worked.

Thanks a lot for your help.