mcpField
I
inventory-system

inventory-system

github.com/jame581开发889176 次安装4 天前更新
代码仓库

关于 inventory-system

面向 Godot 4.3+ 开发者的物品栏系统技能,提供 GDScript 和 C# 实现指导。内容涵盖物品与槽位建模、堆叠规则、装备扩展、UI 绑定及存档序列化。

主要功能

  1. 01以 Resource 定义物品数据
  2. 02槽位管理与堆叠操作
  3. 03物品栏及装备信号
  4. 04网格 UI 与拖放绑定
  5. 05按物品 ID 序列化存档

适用场景

  1. 01实现具有堆叠上限的固定槽位背包
  2. 02将物品栏变化同步到网格 UI
  3. 03扩展装备槽位并汇总属性
  4. 04保存槽位内容并在载入时恢复物品

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/jame581/godotprompter --skill inventory-system

安装后在 Claude Code 中输入/inventory-system确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
core-classes.md
equipment.md
serialization.md
ui-binding.md

详细介绍

Godot 4.3+ 中的物品栏系统

所有示例均适用于 Godot 4.3+,不使用已弃用的 API。本技能涵盖相关决策;具体实现位于 references/ 中(先是 GDScript,然后是 C#)——加载所需的实现即可。

**相关技能:**自定义 Resource 数据容器可参阅 resource-pattern,物品栏序列化可参阅 save-load,物品栏变更通知可参阅 event-bus,物品栏 UI 显示可参阅 hud-system,冒险游戏物品栏可参阅 popochiu。


1. 架构概览

┌─────────────────────────────────────────────────────────┐
│                        UI Layer                         │
│   InventoryUI (Control)                                 │
│     └─ GridContainer                                    │
│           └─ SlotUI × N (Button)                        │
│                 └─ TextureRect (icon) + Label (qty)     │
│                                                         │
│   Connects to: inventory_changed signal                 │
│   Drag-and-drop via _get_drag_data / _drop_data         │
└───────────────────────┬─────────────────────────────────┘
                        │ reads / mutates
┌───────────────────────▼─────────────────────────────────┐
│                    Inventory (Node)                      │
│   slots: Array[InventorySlot]                           │
│   add_item(item, qty) → leftover: int                   │
│   remove_item(item, qty)                                │
│   has_item(item, qty) → bool                            │
│   get_item_count(item) → int                            │
│                                                         │
│   signals: inventory_changed                            │
│             item_added(item, quantity)                  │
│             item_removed(item, quantity)                │
└───────────────────────┬─────────────────────────────────┘
                        │ references
┌───────────────────────▼─────────────────────────────────┐
│                   Data Layer (Resources)                 │
│   ItemData (Resource)                                   │
│     id, name, description, icon, max_stack_size,        │
│     item_type enum                                      │
│                                                         │
│   InventorySlot (inner class / Resource)                │
│     item: ItemData, quantity: int                       │
└─────────────────────────────────────────────────────────┘

2. 重要决策

三个选择会影响每个物品栏。请明确做出选择并说明选了哪项——其余工作都是机械性的。

决策选择原因
物品标识:Resource 还是 Dictionary / JSON.tres 中的 Resource@export 槽位接受类型化物品,Inspector 可编辑它们,且共享实例按引用比较
槽位容器:Resource 还是 RefCountedRefCounted槽位是运行时状态,而非创作资源。使用 Resource 容易导致槽位被保存到磁盘,并重新加载过时的物品副本
add_item 返回值:bool 还是剩余数量剩余 int部分添加很常见(堆叠上限、背包已满)。使用 bool 会迫使调用方重新查询实际放入的数量

如果你的游戏需要其他方案——没有槽位的重量限制背包、可容纳异形物品的网格物品栏、无限堆叠列表——请在开始构建前说明。本文介绍的固定槽位数组不适合作为这三种方案的基础结构。

不易察觉的细节
  • 先填满已有堆叠,再填空槽位——按此顺序分两轮处理。简单地遍历一遍会把同一种物品分散到多个槽位,并在仍有空间时错误地报告背包已满。
  • 每次操作只触发一次 inventory_changed,并在两轮处理完成后触发——不要每触及一个槽位就触发一次。每个槽位都触发会导致一次 add_item 让整个 UI 重绘 N 次。
  • 物品按引用比较。 Godot 会缓存已加载的资源,因此对同一个 .tres 调用 load() 会返回同一实例,slot.item == item 既正确又高效。如果在运行时 duplicate() 物品,这种做法就会失效——应改用 ItemData.id 作为键。
  • 数量达到 0 时将 item 清为 null,否则 is_empty() 会返回错误结果,槽位也无法再次使用。
  • 通过数据阻止堆叠,而不是添加分支——将 EQUIPMENT 和 KEY_ITEM 物品的 max_stack_size 设为 1,不要在 add_item 中为它们添加特殊处理。
  • C#:将 ItemData 标记为 [GlobalClass],否则在创建 .tres 文件时,Inspector 不会将其作为类型提供。
物品栏 API 约定
成员返回值约定
add_item(item, quantity)int未能放入的剩余数量;0 表示已全部添加
remove_item(item, quantity)—最多移除 quantity 个;持有数量不足时不发出通知
has_item(item, quantity)bool对 get_item_count 的便捷封装
get_item_count(item)int汇总所有槽位中的数量
inventory_changed信号每次修改操作只触发一次——用于驱动所有 UI
item_added(item, quantity)信号携带实际添加的数量
item_removed(item, quantity)信号携带实际移除的数量

GDScript 和 C# 中完整的 ItemData、Inventory 与 InventorySlot 实现见:references/core-classes.md


3. 装备扩展

在 Inventory 节点旁添加一个 Equipment 节点,并为其添加装备槽位(HEAD、CHEST、WEAPON 等)。Equipment 持有一个以 SlotType 枚举为键的槽位映射。属性汇总会将已装备物品的 stats Dictionary(添加到 ItemData 的属性)相加;槽位变更时触发 equipment_changed 信号。

完整的 GDScript 和 C# Equipment 类(包含 SlotType 枚举、装备 / 卸下 API 和属性汇总)见 references/equipment.md。


4. UI 绑定

槽位网格 UI:由 Button 槽位控件组成的 GridContainer,每个控件渲染一个 InventorySlot。拖放通过槽位控件上的 _get_drag_data / _drop_data / _can_drop_data 实现。Inventory 发出 inventory_changed;UI 重新渲染受影响的槽位。

完整的 GDScript 和 C# 槽位控件(拖放、悬停预览)、背包网格布局和工具提示接线,请参见 references/ui-binding.md。


5. 序列化

将每个槽位保存为 {id, qty} 键值对(空槽位为 null),不要保存 ItemData 本身或其路径。ItemRegistry 自动加载项会在启动时加载 res://items/,并在加载时将 ID 解析回物品。

有关包含 serialize_inventory / deserialize_inventory 的 GDScript 和 C# ItemRegistry,请参见 references/serialization.md;将结果放入存档文件(其 version 字段请参见 save-load)。



实现检查清单

  • ItemData 继承 Resource,并在 Inspector 中设置稳定的 id 字符串
  • ItemData 文件存放在 res://items/ 下,并提交到版本控制
  • Inventory.add_item() 返回剩余数量;调用方负责处理背包已满的情况
  • inventory_changed 信号驱动所有 UI 更新 — UI 绝不逐帧轮询
  • InventorySlot.remove_from_stack() 在数量达到 0 时将 item 清除为 null
  • 装备槽以 SlotType 枚举为键,而不是字符串,以便在编译时发现拼写错误
  • 需要属性时调用 Equipment.get_total_stat();除非性能分析表明有必要,否则不要缓存结果
  • 序列化只存储 id + quantity — 不要存储完整的 ItemData 对象或资源路径
  • ItemRegistry 在启动时加载物品;所有反序列化都通过它进行
  • 拖放直接交换槽位内容,然后只发出一次 inventory_changed
  • 在 EQUIPMENT 和 KEY_ITEM 类型上将 max_stack_size = 1,以防止堆叠
  • 所有 push_error() 消息都包含类名和方法名,便于追踪

评论

支持 Markdown