How to transfer objects from one inventory to another?

Godot Version

Version 4.7.1

Question

Before we get started, a few important things to note:

  1. I do realize that this is already in another question quite similar to mine, but the way that that user set up his inventory system seemed fairly different from mine. I will link the post regardless. Transfer item between player inventory and chest inventory
  2. There are multiple YouTube tutorials that have to do with this topic, however, the one that i decided to watch did not include this topic, but I got too far into the tutorial now before realizing that. It was a good series regardless. I could redo the inventory from scratch, but whenever you remove very integrated systems in programming it’ll mess a bunch of stuff up, and I would rather try to make this system work before actually doing this. Here is the link to the tutorial: https://www.youtube.com/watch?v=X3J0fSodKgs
  3. I have not tried a ton of methods so far because I am still fairly new to Godot and have zero clue how to go about this, even though I do understand the inventory system.

So, here is my issue. I am making a game that mostly revolves around having to take stuff out of the fridge (basically, the player opens the fridge, grabs something, carries it outside, drops it off outside, and then repeats the process). I have a single slot player inventory resource set up and a twelve slot fridge inventory resource set up. I also have a cursor object that the player can use to select items that are in the fridge.
Here is the code for the general inventory resource:

extends Resource

class_name Inventory

@export var items: Array[InventoryItem]

Here is the code for the inventory item resources:

extends Resource

class_name InventoryItem

@export var name: String = ""
@export var texture: Texture2D

Here is the code for the fridge’s inventory:

extends Control

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

@export var item: InventoryItem

func _ready():
	_update_slots()

func _update_slots():
	for i in range(min(Inventory.items.size(), slots.size())):
		slots[i]._update(Inventory.items[i])

Here is the code for the fridge inventory slots:

extends Panel

@onready var item_to_display: Sprite2D = $CenterContainer/Panel/ItemDisplay

func _update(item: InventoryItem):
	if !item:
		item_to_display.visible = false
	
	else:
		item_to_display.visible = true
		item_to_display.texture = item.texture

Here is the cursor code:

extends CharacterBody2D

var direction
@export var speed := 500
@export var start_x := 515
@export var start_y := 173

func _ready():
	position = Vector2(start_x, start_y)

func _process(_delta: float):
	pass

func _physics_process(_delta: float):
	
	# Movement script
	direction = Input.get_vector("left", "right", "up", "down")
	velocity = direction * speed
	
	move_and_slide()
	
	# Select script
	if Input.is_action_just_pressed("secondary action"):
		print("added 'thing' to inventory")

Here is the player script:

extends CharacterBody2D

class_name Player
@export var speed := 340
@export var Inventory: Inventory
@onready var animated_sprite = $AnimatedSprite2D
var panicked = false
var direction

func _ready():
	Global.on_trigger_player_spawn.connect(_on_spawn)

func _process(_delta):
	pass

# movement script

func _physics_process(_delta):
	direction = Input.get_axis("left", "right")
	if direction:
		velocity.x = direction * speed
		animated_sprite.play("walk_not_panicked")
		animated_sprite.flip_h = direction < 0
	else:
		velocity.x = move_toward(velocity.x, 0, speed)
		animated_sprite.play("idle_not_panicked")
	
	move_and_slide()

func _on_spawn(Position: Vector2, _direction: String):
	global_position = Position

func _collect(item):
	Inventory.insert(item)

If this would be too difficult to insert based on my current code, I have a fallback option that I think I would know how to code, but it may not be quite as nice of a system. Any help is greatly appriciated.

You already have two Inventory resources; transfer is just “take from fridge slot → put in player slot → refresh UI.” Your cursor select is still only a print.

Inventory as pasted has no insert() either, so add something simple:

func insert(item: InventoryItem) -> bool:
	for i in items.size():
		if items[i] == null:
			items[i] = item
			return true
	return false  # full
func take_at(index: int) -> InventoryItem:
	if index < 0 or index >= items.size():
		return null
	var item = items[index]
	items[index] = null
	return item

Cursor (when over a fridge slot):

if Input.is_action_just_pressed("secondary action"):
	var fridge = # your fridge inventory UI / resource
	var player_inv = # player.Inventory
	var slot_index = 0  # however you know which slot the cursor is on
	if player_inv.items[0] != null:
		return  # player already holding something (1-slot)
	var item = fridge.Inventory.take_at(slot_index)
	if item:
		player_inv.insert(item)
		fridge._update_slots()
		# update player HUD slot the same way

Drop-off outside = reverse: take_at(0) from player, insert into fridge (or a “outside” inventory).

How you get slot_index depends on your cursor : overlap an Area2D on each slot, or grid math from cursor position. That’s the missing piece in the tutorial, not a full rewrite.

If fridge and player share the same .tres by mistake, they’ll fight each other. Each needs its own inventory resource.

The print was just a placeholder. I will try this however. Hopefully this works, thanks.

Okay, I tried it. The issue is that when I try to actually select the item that game freezes and throws up the following error: _physics_process: Invalid access to property or key ‘Inventory’ on a base object of type ‘Resource (Inventory)’.
I have encountered this issue in the past, but I do not understand the issue. What is a key? Why doesn’t it have access? I have looked online but the only things I could find were saying that @onready was an issue and that having var and class_names being the same were issues, or it was dealing with a 3d game. There is no @onready in my script. Any help will be appriciated. Thanks.

That error means you’re doing .Inventory on something that is already an Inventory resource. Resources don’t have an Inventory property; they are the inventory.

So if fridge is the .tres / resource, call:

fridge.take_at(slot_index)

not fridge.Inventory.take_at(...).

If fridge is the fridge UI (Control), then fridge.Inventory is fine only if that node still has the Inventory variable. Easiest cleanup: stop naming variables the same as the class.

# Inventory resource script stays class_name Inventory
# fridge UI:
@onready var inventory: Inventory = preload("res://inventory/fridge_inventory.tres")
# player:
@export var inventory: Inventory

Then:

var item = fridge_ui.inventory.take_at(slot_index)
if item:
	player.inventory.insert(item)
	fridge_ui._update_slots()

key in that error just means “property name” (Inventory). Godot looked for it on the resource and didn’t find it.