背包不是一个数组
很多个人游戏早期会把背包做成一个简单数组:拾取物品时 items.add(id),使用时从数组删除。原型阶段这样足够,但准备上 Steam 后,问题会迅速增加:物品能否堆叠,装备和消耗品是否共用背包,旧存档里的物品 ID 改名怎么办,玩家背包满了拾取失败如何反馈,Demo 里的物品到正式版是否保留,补丁删除物品后旧存档如何加载。
库存系统的难点不是显示格子,而是维护清楚规则。每个物品的身份、数量、状态、来源和存档方式都要稳定。否则玩家会遇到装备消失、道具重复、背包 UI 和实际数据不一致这类很难接受的问题。
先定义物品数据
物品数据应和具体实例分开。数据表描述“铁剑是什么”,实例描述“玩家背包里这把铁剑当前耐久是多少”。基础表可以这样:
| 字段 | 示例 | 说明 |
|---|---|---|
item_id | weapon_iron_sword | 稳定 ID |
name_key | item.iron_sword.name | 本地化文本 |
type | weapon | 分类 |
stackable | false | 是否堆叠 |
max_stack | 1 | 最大堆叠 |
icon | icon_iron_sword | UI 图标 |
equip_slot | main_hand | 可装备槽 |
sell_price | 30 | 经济系统引用 |
显示名称可以改,item_id 不要轻易改。上线后玩家存档、成就、任务、商店和日志都可能引用它。需要废弃物品时,也先保留 ID 和迁移规则,而不是直接删除。
实例数据和堆叠规则
消耗品和材料通常可以堆叠,装备通常不能简单堆叠,因为每件装备可能有耐久、强化等级、词条或绑定状态。实例数据可以包含:
| 字段 | 用途 |
|---|---|
instance_id | 唯一实例,装备常用 |
item_id | 指向物品表 |
count | 堆叠数量 |
durability | 耐久 |
mods | 随机词条或强化 |
source | 掉落、商店、任务 |
堆叠时要定义清楚:同 ID 是否都能合并,强化过的道具是否能合并,任务物品是否占格子,超过最大堆叠时如何拆分。不要把堆叠逻辑写在 UI 拖拽里,应该放在库存服务中。
装备槽设计
装备槽要服务玩法,而不是照搬复杂 RPG。一个小体量动作游戏可能只需要主武器、副武器、饰品;解谜游戏可能只有工具槽;Roguelite 可能有主动道具和被动道具。
| 槽位 | 规则 |
|---|---|
main_hand | 只能装备武器 |
off_hand | 盾或副手工具 |
trinket_1 | 被动饰品 |
active_item | 可主动使用道具 |
槽位变化要触发角色属性、动画、UI 和存档更新。装备不是简单移动物品位置,它会影响战斗、外观、数值、快捷栏和成就。最好通过统一接口 Equip(instance_id, slot) 处理,避免 UI、任务脚本和商店各自改数据。
拾取流程
拾取物品要考虑很多边界:
- 背包是否有空间。
- 可堆叠物品是否能合并。
- 任务物品是否必须拾取。
- 拾取后地面物是否消失。
- 读档后是否重复出现。
- 多语言提示是否正确。
- 手柄操作是否能选择拾取。
拾取失败也要有反馈。背包满时提示“背包已满”,而不是让玩家按键没有反应。关键任务物品可以不占普通背包,或者在背包满时仍允许拾取,但规则要一致。
背包 UI
背包 UI 要显示物品图标、数量、类型、描述、可用操作和快捷提示。不要让玩家猜某个道具能不能用、能不能卖、能不能装备。
UI 信息可以分层:
| 层级 | 内容 |
|---|---|
| 格子 | 图标、数量、品质或状态 |
| 详情面板 | 名称、描述、属性变化 |
| 操作菜单 | 使用、装备、丢弃、拆分、排序 |
| 筛选 | 武器、材料、任务、消耗品 |
手柄导航尤其要测。格子网格、详情面板和操作菜单之间的焦点切换容易出错。删除或丢弃物品要有确认,默认焦点不要放在危险操作上。
存档和迁移
库存存档至少保存物品 ID、实例 ID、数量、装备槽和必要状态。不要把整张物品配置复制进存档,否则补丁改数值时旧存档不会更新。存档保存引用,运行时从当前配置读取基础属性。
迁移策略:
| 变化 | 处理 |
|---|---|
| 物品改名 | 只改本地化文本,不影响存档 |
| 物品删除 | 迁移成替代物品或补偿资源 |
| 最大堆叠变化 | 加载时拆分或合并 |
| 槽位改名 | 迁移装备槽 |
| 装备属性变化 | 读取新配置,保留实例状态 |
每次物品表大改,都要用旧存档加载测试。库存问题一旦影响玩家装备,反馈会非常强烈。
排序和筛选
排序不是必须第一天做,但背包物品超过一定数量后很有必要。排序规则要稳定:按类型、获得时间、品质、名称或可用状态。不要每次打开背包顺序都变,玩家会找不到东西。
筛选也要保持状态。玩家在材料页查看合成材料,关闭再打开是否仍停留在材料页,可以按项目决定,但行为要一致。
与经济和任务系统的关系
商店购买、任务奖励、敌人掉落、合成消耗都应该通过同一库存接口。任务完成发放物品时,如果背包满了怎么办?商店出售装备时,已装备物品能不能卖?合成消耗材料时,多个堆叠如何扣除?这些规则不能散落在各系统。
建议库存服务提供清楚方法:CanAdd、AddItem、RemoveItem、EquipItem、UnequipItem、CanSell。其他系统先询问,再执行。
发布前测试清单
| 测试 | 检查 |
|---|---|
| 拾取堆叠物 | 数量合并正确 |
| 背包满拾取 | 有反馈,不丢物品 |
| 装备和卸下 | 属性、外观、UI 同步 |
| 丢弃物品 | 确认框和地面物 |
| 商店购买 | 金币和背包同步 |
| 任务奖励 | 背包满时策略正确 |
| 读档 | 物品、装备槽和数量恢复 |
| 旧存档 | 物品表变更后可加载 |
最终检查清单
- 物品配置和物品实例分开。
- 物品 ID 稳定,不依赖显示名称。
- 堆叠、装备、拾取和丢弃规则在服务层处理。
- 背包 UI 支持键鼠和手柄焦点。
- 存档保存引用和实例状态,不复制整份配置。
- 物品表变化有迁移策略。
- 经济、任务、商店通过统一库存接口操作。
- 发布前用旧存档和满背包路径回归。
库存装备系统越早定规则,后期越少返工。对个人 Steam 游戏来说,玩家可以接受背包不复杂,但很难接受物品丢失、装备错乱或奖励无法领取。
快捷栏和背包同步
如果游戏有快捷栏,快捷栏不要复制物品,而应引用背包中的实例或物品 ID。否则玩家使用、出售、丢弃物品后,快捷栏可能还显示旧内容。快捷栏更新规则要清楚:物品数量为零时清空,装备替换时刷新,读档后重新校验。
快捷栏也要支持手柄和键鼠两种操作。手柄玩家通常需要轮盘或方向键选择,键鼠玩家可能习惯数字键。两者都应通过同一套使用接口调用物品效果。
背包容量的设计意图
背包容量不是单纯限制玩家。容量小会制造取舍,但也可能让玩家频繁整理。容量大更轻松,但会让排序和筛选更重要。决定容量前要看游戏类型:生存游戏可以让容量成为压力,动作冒险则不宜频繁打断节奏。
如果容量是付费或升级目标,要让玩家感受到改善。只增加一两个格子但价格很高,会显得不值得。
物品来源追踪
记录物品来源能帮助排查问题。比如某把剑来自商店、某个任务奖励、某个掉落表。玩家反馈重复获得任务物品时,日志里如果有来源字段,就能快速定位是任务重复触发还是背包合并错误。
来源也能用于统计:哪些商店物品没人买,哪些掉落太多,哪些奖励被玩家丢弃。即使不做在线遥测,内部测试时也很有价值。
物品锁定和防误操作
装备、任务物品、稀有材料最好支持锁定或保护。玩家不应轻易卖掉主线钥匙,也不应误分解当前装备。可以给任务物品禁止丢弃,给已装备物品出售前二次确认,给稀有物品加醒目标记。
这些保护不会让系统复杂太多,却能减少非常糟糕的玩家体验。背包系统最怕的是玩家一次误操作导致长时间进度受损。
补丁新增物品的策略
发售后新增物品时,要考虑旧存档。新物品是否进入商店,是否加入掉落池,是否需要新教程,是否影响成就。不要只把物品表加一行就结束。新增装备还可能需要图标、特效、音效、本地化和商店描述。
补丁前用旧存档进入商店和掉落场景,确认新物品不会破坏已有经济。
继续阅读
探索更多技术文章
浏览归档,发现更多关于系统设计、工具链和工程实践的内容。