Files
loneseDocument/Plugins/Item/FItemInstance.md
meishibiezb 29a3f77908 init
2026-06-04 21:44:13 +08:00

5.8 KiB
Raw Permalink Blame History

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。