6.3 KiB
UDefaultContainer
基本信息
- 类型: UCLASS(BlueprintType, Blueprintable)
- 父类: UObject, 实现 IItemContainer
- 源文件: Plugins/Item/Source/Item/Public/DefaultContainer.h
- 模块: Item
功能概述
IItemContainer的参考实现。将物品存储在TArray<TUniquePtr>中。实现所有接口方法:查询、移动、创建、带类型检查的属性读写。Blueprintable允许设计师扩展。TODO计划切换为TMap以提升性能。
设计用意
默认的具体容器实现。简单的扁平数组存储。Blueprintable标记允许子类添加约束(槽位、堆叠)。为其他容器实现提供参考。
职责范围
完整的IItemContainer实现。处理物品存储、检索、移动、创建和属性访问。使用UItemRegistrySubsystem进行物品定义查找,使用FItemViewFactory生成视图。
项目内依赖
| 依赖项 | 关系 | 源文件 |
|---|---|---|
| ItemContainer.h | #include (实现) | Plugins/Item/Source/Item/Public/ItemContainer.h |
| ItemRegistrySubsystem.h | #include (在.cpp中) | Plugins/Item/Source/Item/Public/ItemRegistrySubsystem.h |
| ItemViewFactory.h | #include (在.cpp中) | Plugins/Item/Source/Item/Public/ItemViewFactory.h |
| ItemFactory.h | #include (在.cpp中) | Plugins/Item/Source/Item/Public/ItemFactory.h |
对外接口
UDefaultContainer 实现了 IItemContainer 的全部接口,对外暴露以下方法(全部继承自 IItemContainer,此处列出的均为 override 实现):
查询接口:
- GetItemViews() const → TArray: 遍历内部 Items 数组,通过 UItemRegistrySubsystem 获取每个物品的 FItemDef,调用 FItemViewFactory::CreateView 构造视图。注册表不可用时返回空数组(DefaultContainer.cpp:54-66)。
- GetItemViewByID(const FGuid&) const → FItemView: 按 ID 查找。未找到返回空 FItemView(DefaultContainer.cpp:69-81)。
- GetItemCount() const → int32: 返回 Items.Num()(DefaultContainer.cpp:84-86)。
变更接口:
- MoveItem(const FGuid&, const TScriptInterface&) → bool: 从内部数组取出物品(MoveTemp),调用 RemoveAt,然后通过目标容器的 InjectPayload 注入。目标容器无效或物品不存在时返回 false(DefaultContainer.cpp:89-111)。
- CreateItem(FName, TArray&, int32 Count = 1) → bool: 从注册表获取 FItemDef,检查 ItemName 非空,循环调用 ItemFactory::CreateItemInstance 创建指定数量物品,每个物品通过自身的 InjectPayload 添加。新物品 ID 追加到 NewItemIDs(DefaultContainer.cpp:113-127)。
属性接口(CustomThunk 底层实现):
- Internal_GetPropertyRaw: 按 ItemID 线性查找物品 → 从属性包中查找属性描述 → 类型兼容性检查后从属性包内存拷贝到蓝图引脚内存(DefaultContainer.cpp:137-187)。
- Internal_SetPropertyRaw: 相同的查找和类型检查流程,反向拷贝(从蓝图引脚写入属性包)(DefaultContainer.cpp:189-230)。
内部接口:
- InjectPayloadImpl(TUniquePtr): 接收物品所有权,简单的 Items.Add(DefaultContainer.cpp:129-135)。
存储: 内部使用 TArray<TUniquePtr> Items 存储物品。当前为线性查找(O(n)),TODO 计划切换为 TMap 以提升性能。类标记为 BlueprintType 和 Blueprintable,可在编辑器中创建 BP_DefaultContainer 子类。
使用方法
UDefaultContainer 作为 IItemContainer 的参考实现,可直接在 C++ 中实例化,或创建 Blueprint 子类(如 BP_DefaultContainer)在编辑器中引用。
在 C++ 中使用: 容器需要绑定到 GameInstance 的 World 上下文才能获取注册表(通过 GetRegistry 辅助函数,DefaultContainer.cpp:44-52)。创建物品和查询都依赖注册表。
在 Blueprint 中使用: BP_DefaultContainer 是 UDefaultContainer 的蓝图子类(无额外逻辑),可在编辑器中作为资产创建。BP_InventoryComp 在编辑器中持有 BP_DefaultContainer 的引用,通过它对容器进行操作:
- 调用 CreateItem 创建物品(需在 Authority 侧执行)。
- 调用 GetItemViews 获取物品列表用于 UI 显示。
- 调用 MoveItem 将物品移动到其他容器。
实现自定义容器: 继承 UDefaultContainer 并覆写虚方法即可创建自定义容器(如带槽位限制、堆叠功能的容器)。由于类标记了 Blueprintable,也可以在 Blueprint 中继承。
当前实现的限制:
- 存储使用 TArray 线性查找(O(n)),TODO 计划切换为 TMap 以提升性能(DefaultContainer.h:32)。
- 属性读写中的名称清理(点号→下划线)当前在 Internal_GetPropertyRaw / Internal_SetPropertyRaw 中处理,TODO 计划提取到 NVI 层。
用例
Plugins/Item/Source/Item/Public/DefaultContainer.h:15-34-- UDefaultContainer 类声明(继承 UObject + IItemContainer,声明所有接口方法和 Items 成员)。Plugins/Item/Source/Item/Private/DefaultContainer.cpp:44-52-- GetRegistry 静态辅助函数,从 WorldContext 获取 UItemRegistrySubsystem。Plugins/Item/Source/Item/Private/DefaultContainer.cpp:54-66-- GetItemViews 实现:遍历 Items 并为每个物品调用 FItemViewFactory::CreateView。Plugins/Item/Source/Item/Private/DefaultContainer.cpp:69-81-- GetItemViewByID 实现。Plugins/Item/Source/Item/Private/DefaultContainer.cpp:84-86-- GetItemCount 实现。Plugins/Item/Source/Item/Private/DefaultContainer.cpp:89-111-- MoveItem 实现:MoveTemp + RemoveAt + InjectPayload。Plugins/Item/Source/Item/Private/DefaultContainer.cpp:113-127-- CreateItem 实现:获取定义 → 工厂创建 → InjectPayload。Plugins/Item/Source/Item/Private/DefaultContainer.cpp:129-134-- InjectPayloadImpl 实现。Plugins/Item/Source/Item/Private/DefaultContainer.cpp:137-187-- Internal_GetPropertyRaw 实现(属性包读取 + 类型兼容性检查)。Plugins/Item/Source/Item/Private/DefaultContainer.cpp:189-230-- Internal_SetPropertyRaw 实现(属性包写入 + 类型兼容性检查)。Document/Content/Blueprints/BP_DefaultContainer.md-- BP_DefaultContainer 是 UDefaultContainer 的 Blueprint 子类,在编辑器中作为可引用资产使用。Document/Content/Blueprints/BP_InventoryComp.md-- BP_InventoryComp 持有 BP_DefaultContainer 引用并包装其操作。