101 lines
5.8 KiB
Markdown
101 lines
5.8 KiB
Markdown
# FItemInstance
|
||
|
||
## 基本信息
|
||
- **类型**: USTRUCT
|
||
- **父类**: (无)
|
||
- **源文件**: Plugins/Item/Source/Item/Public/ItemFactory.h
|
||
- **模块**: Item
|
||
|
||
## 功能概述
|
||
单个运行时物品的内部重量级表示。包含唯一GUID、类型键,以及FInstancedPropertyBag中的动态属性。由容器通过TUniquePtr独占拥有。具有friend class ItemFactory用于受控构造。
|
||
|
||
## 设计用意
|
||
物品的运行时真值源。刻意不作为BlueprintType公开。TUniquePtr所有权确保清晰的单拥有者语义。FInstancedPropertyBag允许每个物品拥有任意的动态属性。友元控制构造防止产生孤立物品。
|
||
|
||
## 职责范围
|
||
持有单个物品实例的所有运行时状态。通过TUniquePtr在容器间经由InjectPayload传递。不向容器/工厂外部暴露修改接口。
|
||
|
||
## 项目内依赖
|
||
(无项目内依赖)
|
||
|
||
## 对外接口
|
||
FItemInstance 是内部使用的 USTRUCT(非 BlueprintType),不作为公共 API 直接暴露给外部代码。其字段均标记为 UPROPERTY()(无 BlueprintReadOnly),供容器和工厂内部访问。
|
||
|
||
外部调用方不应直接创建或修改 FItemInstance。与 FItemInstance 交互的唯一入口是通过以下间接途径:
|
||
|
||
- **创建**: 通过 UDefaultContainer::CreateItem(或 IItemContainer::CreateItem),内部调用 ItemFactory::CreateItemInstance。
|
||
- **查询**: 通过 IItemContainer::GetItemViews() 获取 FItemView 快照,而非直接访问 FItemInstance。
|
||
- **属性读写**: 通过 IItemContainer::GetItemProperty / SetItemProperty,而非直接操作 FItemInstance::ItemData。
|
||
|
||
内部字段供 ItemFactory 和容器实现者使用:
|
||
- **ItemID** (FGuid): 物品唯一标识,由工厂在创建时通过 FGuid::NewGuid() 生成。
|
||
- **ItemType** (FName): 物品类型名称,对应 DataTable 中的行名,用于在注册表中查找 FItemDef。
|
||
- **ItemData** (FInstancedPropertyBag): 物品的动态属性包。包含从 FItemDef::DefaultItemProps 转换来的属性,以及可选的 OverrideProps 合并值。当 bHasTracer 为 true 时还包含 Internal_ItemTracer 键。
|
||
|
||
所有权模型:FItemInstance 只能通过 TUniquePtr 持有,禁止复制(拷贝构造 / 赋值运算符保留但标记为 default,实际应避免使用)。移动语义开放(移动构造和移动赋值 = default),支持在容器间转移所有权。
|
||
|
||
## 使用方法
|
||
FItemInstance 不直接被外部代码创建或操作。外部代码通过容器接口间接交互。
|
||
|
||
**创建(仅通过 ItemFactory):**
|
||
```cpp
|
||
// ItemFactory.cpp:6-24
|
||
TUniquePtr<FItemInstance> ItemFactory::CreateItemInstance(
|
||
const FItemDef& ItemDef, FName ItemType,
|
||
const FInstancedPropertyBag* OverrideProps)
|
||
{
|
||
TUniquePtr<FItemInstance> Instance = MakeUnique<FItemInstance>();
|
||
Instance->ItemID = FGuid::NewGuid();
|
||
Instance->ItemType = ItemType;
|
||
ConvertDefaultProps(ItemDef.DefaultItemProps, Instance->ItemData);
|
||
if (OverrideProps)
|
||
MergePropertyBag(*OverrideProps, Instance->ItemData);
|
||
if (ItemDef.bHasTracer)
|
||
{
|
||
Instance->ItemData.AddProperty(UInternalItemProperty::ItemTracer(),
|
||
EPropertyBagPropertyType::Object, UItemTracer::StaticClass());
|
||
UItemTracer* NewTracer = NewObject<UItemTracer>();
|
||
Instance->ItemData.SetValueObject(
|
||
UInternalItemProperty::ItemTracer(), NewTracer);
|
||
}
|
||
return Instance;
|
||
}
|
||
```
|
||
|
||
**存储(由 UDefaultContainer 管理):**
|
||
```cpp
|
||
// DefaultContainer.h:33
|
||
TArray<TUniquePtr<struct FItemInstance>> Items;
|
||
|
||
// DefaultContainer.cpp:129-135 - 注入存储
|
||
void UDefaultContainer::InjectPayloadImpl(TUniquePtr<FItemInstance> Payload)
|
||
{
|
||
if (Payload.IsValid())
|
||
Items.Add(MoveTemp(Payload));
|
||
}
|
||
```
|
||
|
||
**读取属性(由容器内部处理):**
|
||
容器通过 ItemData 读取属性值和描述符。例如 DefaultContainer.cpp:137-187 的 Internal_GetPropertyRaw 中:
|
||
```cpp
|
||
const FPropertyBagPropertyDesc* Desc =
|
||
Bag->FindPropertyDescByName(FixedName);
|
||
void* BagMemory = FoundItem->ItemData.GetMutableValue().GetMemory();
|
||
void* SourceAddr = Desc->CachedProperty->ContainerPtrToValuePtr<void>(BagMemory);
|
||
```
|
||
|
||
**在所有容器间转移所有权:**
|
||
通过 MoveTemp + InjectPayload 组合操作。物品的 TUniquePtr 所有权从源容器移至目标容器(DefaultContainer.cpp:104-108)。
|
||
|
||
## 用例
|
||
- `Plugins/Item/Source/Item/Public/ItemFactory.h:60-82` -- FItemInstance 结构体定义(ItemID、ItemType、ItemData 三个字段 + 友元声明 + 构造/移动/拷贝控制)。
|
||
- `Plugins/Item/Source/Item/Private/ItemFactory.cpp:6-24` -- ItemFactory::CreateItemInstance 创建 FItemInstance 的唯一入口(MakeUnique + 填充字段 + 属性转换 + Tracer 创建)。
|
||
- `Plugins/Item/Source/Item/Private/DefaultContainer.cpp:60-64` -- GetItemViews 遍历 Items 数组中的 TUniquePtr<FItemInstance> 并解引用传递给 FItemViewFactory。
|
||
- `Plugins/Item/Source/Item/Private/DefaultContainer.cpp:73-78` -- GetItemViewByID 按 ID 匹配 Items 中的 FItemInstance 指针。
|
||
- `Plugins/Item/Source/Item/Private/DefaultContainer.cpp:96-108` -- MoveItem 通过 MoveTemp 转移 FItemInstance 所有权,从源数组 RemoveAt 后注入目标容器。
|
||
- `Plugins/Item/Source/Item/Private/DefaultContainer.cpp:121-124` -- CreateItem 接收工厂返回的 TUniquePtr<FItemInstance> 并注入自身。
|
||
- `Plugins/Item/Source/Item/Private/DefaultContainer.cpp:129-134` -- InjectPayloadImpl 接收 TUniquePtr<FItemInstance> 并 Add 到 Items 数组。
|
||
- `Plugins/Item/Source/Item/Private/DefaultContainer.cpp:140-186` -- Internal_GetPropertyRaw 从 FoundItem->ItemData 中按属性名称读取值。
|
||
- `Plugins/Item/Source/Item/Private/ItemContainer.cpp:45-67` -- InjectPayload NVI 从 Payload->ItemData 中读取 Tracer 并更新位置。
|
||
- `Plugins/Item/Source/Item/Private/ItemViewFactory.cpp:11-19` -- PopulateCommon 从 Instance.ItemID / Instance.ItemType 读取字段填入 FItemView。
|