This commit is contained in:
meishibiezb
2026-06-04 21:37:53 +08:00
parent b0d2a0e2e7
commit 29a3f77908
63 changed files with 4068 additions and 1 deletions

View File

@@ -0,0 +1,79 @@
# UDefaultContainer
## 基本信息
- **类型**: UCLASS(BlueprintType, Blueprintable)
- **父类**: UObject, 实现 IItemContainer
- **源文件**: Plugins/Item/Source/Item/Public/DefaultContainer.h
- **模块**: Item
## 功能概述
IItemContainer的参考实现。将物品存储在TArray<TUniquePtr<FItemInstance>>中。实现所有接口方法查询、移动、创建、带类型检查的属性读写。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<FItemView>: 遍历内部 Items 数组,通过 UItemRegistrySubsystem 获取每个物品的 FItemDef调用 FItemViewFactory::CreateView 构造视图。注册表不可用时返回空数组DefaultContainer.cpp:54-66
- **GetItemViewByID(const FGuid&) const** → FItemView: 按 ID 查找。未找到返回空 FItemViewDefaultContainer.cpp:69-81
- **GetItemCount() const** → int32: 返回 Items.Num()DefaultContainer.cpp:84-86
**变更接口:**
- **MoveItem(const FGuid&, const TScriptInterface<IItemContainer>&)** → bool: 从内部数组取出物品MoveTemp调用 RemoveAt然后通过目标容器的 InjectPayload 注入。目标容器无效或物品不存在时返回 falseDefaultContainer.cpp:89-111
- **CreateItem(FName, TArray<FGuid>&, int32 Count = 1)** → bool: 从注册表获取 FItemDef检查 ItemName 非空,循环调用 ItemFactory::CreateItemInstance 创建指定数量物品,每个物品通过自身的 InjectPayload 添加。新物品 ID 追加到 NewItemIDsDefaultContainer.cpp:113-127
**属性接口CustomThunk 底层实现):**
- **Internal_GetPropertyRaw**: 按 ItemID 线性查找物品 → 从属性包中查找属性描述 → 类型兼容性检查后从属性包内存拷贝到蓝图引脚内存DefaultContainer.cpp:137-187
- **Internal_SetPropertyRaw**: 相同的查找和类型检查流程反向拷贝从蓝图引脚写入属性包DefaultContainer.cpp:189-230
**内部接口:**
- **InjectPayloadImpl(TUniquePtr<FItemInstance>)**: 接收物品所有权,简单的 Items.AddDefaultContainer.cpp:129-135
**存储:**
内部使用 TArray<TUniquePtr<FItemInstance>> 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 引用并包装其操作。