5.8 KiB
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):
// 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 管理):
// 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 中:
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 并解引用传递给 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 并注入自身。Plugins/Item/Source/Item/Private/DefaultContainer.cpp:129-134-- InjectPayloadImpl 接收 TUniquePtr 并 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。