godot-inventory-system

安装量: 57
排名: #13118

安装

npx skills add https://github.com/thedivergentai/gd-agentic-skills --skill godot-inventory-system

Inventory System Slot management, stacking logic, and resource-based items define robust inventory systems. Available Scripts grid_inventory_logic.gd Expert grid inventory with tetris-style placement logic. inventory_grid.gd Grid-based inventory controller with drag-and-drop foundations and auto-sorting. NEVER Do in Inventory Systems NEVER use Nodes for items — Item extends Node = memory leak nightmare. Inventory with 100 items = 100 nodes in tree. Use Item extends Resource for save compatibility. NEVER forget to check max_stack before adding — add_item() without stack logic = items disappear silently. ALWAYS attempt stacking BEFORE creating new slots. NEVER modify inventory directly from UI — InventorySlotUI.item = null on click = desynced state. UI should emit signals, Inventory model updates, THEN UI refreshes via signals. NEVER use float for item quantities — Floating-point error: 10.0 - 0.1 * 100 ≠ 0. Use int for countable items. Only use float for weight/volume limits. NEVER forget to validate weight/capacity before adding — Player adds 1000kg item to 100kg inventory? Must check get_total_weight() + item.weight * amount <= max_weight BEFORE adding. NEVER emit inventory_changed inside loop — Adding 100 items = 100 UI refreshes = lag spike. Batch operations, emit ONCE after loop completes. Core Architecture

item.gd (Resource)

class_name Item extends Resource @ export var id : String @ export var display_name : String @ export var icon : Texture2D @ export var max_stack : int = 1 @ export var weight : float = 0.0 @export_multiline var description : String Inventory Manager

inventory.gd

class_name Inventory extends Resource signal item_added ( item : Item , amount : int ) signal item_removed ( item : Item , amount : int ) signal inventory_changed @ export var slots : Array [ InventorySlot ] = [ ] @ export var max_slots : int = 20 @ export var max_weight : float = 100.0 func _init ( ) -> void : slots . resize ( max_slots ) for i in max_slots : slots [ i ] = InventorySlot . new ( ) func add_item ( item : Item , amount : int = 1 ) -> bool : var remaining := amount

Try stacking first

if item . max_stack

1 : for slot in slots : if slot . item == item and slot . amount < item . max_stack : var space := item . max_stack - slot . amount var to_add := mini ( space , remaining ) slot . amount += to_add remaining -= to_add if remaining <= 0 : item_added . emit ( item , amount ) inventory_changed . emit ( ) return true

Add to empty slots

while remaining

0 : var empty_slot := find_empty_slot ( ) if empty_slot == null : return false

Inventory full

var to_add := mini ( item . max_stack , remaining ) empty_slot . item = item empty_slot . amount = to_add remaining -= to_add item_added . emit ( item , amount ) inventory_changed . emit ( ) return true func remove_item ( item : Item , amount : int = 1 ) -> bool : var remaining := amount for slot in slots : if slot . item == item : var to_remove := mini ( slot . amount , remaining ) slot . amount -= to_remove remaining -= to_remove if slot . amount <= 0 : slot . clear ( ) if remaining <= 0 : item_removed . emit ( item , amount ) inventory_changed . emit ( ) return true return false

Not enough items

func has_item ( item : Item , amount : int = 1 ) -> bool : var count := 0 for slot in slots : if slot . item == item : count += slot . amount return count

= amount func find_empty_slot ( ) -> InventorySlot : for slot in slots : if slot . is_empty ( ) : return slot return null func get_total_weight ( ) -> float : var total := 0.0 for slot in slots : if slot . item : total += slot . item . weight * slot . amount return total Inventory Slot

inventory_slot.gd

class_name InventorySlot extends Resource signal slot_changed var item : Item = null var amount : int = 0 func is_empty ( ) -> bool : return item == null func clear ( ) -> void : item = null amount = 0 slot_changed . emit ( ) Equipment System

equipment.gd

class_name Equipment extends Resource signal equipment_changed ( slot : String , item : Item ) @ export var weapon : Item = null @ export var armor : Item = null @ export var accessory : Item = null func equip ( slot : String , item : Item ) -> Item : var old_item : Item = null match slot : "weapon" : old_item = weapon weapon = item "armor" : old_item = armor armor = item "accessory" : old_item = accessory accessory = item equipment_changed . emit ( slot , item ) return old_item func unequip ( slot : String ) -> Item : return equip ( slot , null ) func get_total_stats ( ) -> Dictionary : var stats := { "attack" : 0 , "defense" : 0 , "speed" : 0 } for item in [ weapon , armor , accessory ] : if item and item . has ( "stats" ) : for key in item . stats : stats [ key ] += item . stats [ key ] return stats UI Integration

inventory_ui.gd

extends Control @ onready var grid := $GridContainer var inventory : Inventory func _ready ( ) -> void : inventory . inventory_changed . connect ( refresh_ui ) refresh_ui ( ) func refresh_ui ( ) -> void :

Clear existing

for child in grid . get_children ( ) : child . queue_free ( )

Create slot UI

for slot in inventory . slots : var slot_ui := InventorySlotUI . new ( ) slot_ui . setup ( slot ) grid . add_child ( slot_ui ) Crafting Integration

crafting_recipe.gd

class_name CraftingRecipe extends Resource @ export var result : Item @ export var result_amount : int = 1 @ export var requirements : Array [ CraftingRequirement ] func can_craft ( inventory : Inventory ) -> bool : for req in requirements : if not inventory . has_item ( req . item , req . amount ) : return false return true func craft ( inventory : Inventory ) -> bool : if not can_craft ( inventory ) : return false

Remove ingredients

for req in requirements : inventory . remove_item ( req . item , req . amount )

Add result

inventory . add_item ( result , result_amount ) return true Save/Load func save_inventory ( ) -> Dictionary : return { "slots" : slots . map ( func ( s ) : return s . to_dict ( ) ) } func load_inventory ( data : Dictionary ) -> void : for i in data . slots . size ( ) : slots [ i ] . from_dict ( data . slots [ i ] ) inventory_changed . emit ( ) Best Practices Use Resources - Items as Resources, not class instances Signal-Driven UI - Emit signals, let UI listen Stack Logic - Always check max_stack first Weight Limits - Validate before adding Reference Related: godot-save-load-systems , godot-resource-data-patterns Related Master Skill: godot-master

返回排行榜