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

88 lines
4.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# UItemTracer
## 基本信息
- **类型**: UCLASS(BlueprintType)
- **父类**: UObject
- **源文件**: Plugins/Item/Source/Item/Public/ItemFactory.h
- **模块**: Item
## 功能概述
嵌入在FItemInstance属性包中的轻量级追踪对象。存储当前容器位置并暴露OnItemMoved多播委托。提供Blueprint查询函数用于查询物品位置。
## 设计用意
解决"物品在哪"的问题无需全局注册表。存在于物品的属性包中随物品迁移。由IItemContainer::InjectPayload NVI包装自动更新。OnItemMoved委托使UI/任务系统能响应物品移动事件。
## 职责范围
追踪和广播物品位置变化。由InjectPayload在插入时更新位置。UPROPERTY位置使用TObjectPtr非强引用避免泄漏。
## 项目内依赖
(无项目内依赖)
## 对外接口
UItemTracer 是 BlueprintType嵌入在物品的属性包中键名为 Internal_ItemTracer随物品在容器间迁移。外部代码通过属性包获取 Tracer 引用后,可调用以下接口:
**Blueprint 可调用:**
- **GetItemLocation()** (BlueprintPure, BlueprintAuthorityOnly) → const UObject*: 返回物品当前所在的 UObject 位置。在 InjectPayload NVI 中此位置被设置为容器对象Cast<UObject>(this))。返回值可能为空(物品尚未被注入任何容器)。
- **FindActorInOuterChain()** (BlueprintPure, BlueprintAuthorityOnly) → const AActor*: 从物品位置出发,沿 Outer 链向上查找第一个 AActor。如果物品容器是 Actor 的组件/子对象,此方法可追溯到所属 Actor。找不到则返回 nullptr。
**委托:**
- **OnItemMoved** (FOnItemMoved, BlueprintAssignable): DYNAMIC_MULTICAST_DELEGATE_OneParam 类型的动态多播委托。在 IItemContainer::InjectPayload 中被广播(参数为 Tracer 自身。UI 或任务系统可绑定此委托以响应物品移动事件。
**C++ 专用:**
- **SetItemLocation(UObject*)**: 设置 Tracer 的位置引用。不暴露到 Blueprint。仅由 IItemContainer::InjectPayload NVI 调用ItemContainer.cpp:59确保位置更新与移动广播的原子性。
## 使用方法
UItemTracer 由 ItemFactory 创建并嵌入物品属性包,由 InjectPayload 自动更新。外部代码(如 Blueprint UI从物品属性包中获取 Tracer 引用后使用。
**创建ItemFactory.cpp:17-22**
```cpp
if (ItemDef.bHasTracer)
{
Instance->ItemData.AddProperty(UInternalItemProperty::ItemTracer(),
EPropertyBagPropertyType::Object, UItemTracer::StaticClass());
UItemTracer* NewTracer = NewObject<UItemTracer>();
Instance->ItemData.SetValueObject(
UInternalItemProperty::ItemTracer(), NewTracer);
}
```
**位置更新ItemContainer.cpp:45-67 - InjectPayload NVI**
```cpp
void IItemContainer::InjectPayload(TUniquePtr<struct FItemInstance> Payload)
{
if (!Payload.IsValid()) return;
const FName PropName = UInternalItemProperty::ItemTracer();
if (const FPropertyBagPropertyDesc* Desc =
Payload->ItemData.FindPropertyDescByName(PropName))
{
if (UObject* SelfAsObject = Cast<UObject>(this))
{
TValueOrError<UObject*, EPropertyBagResult> Result =
Payload->ItemData.GetValueObject(PropName);
if (Result.HasValue())
{
if (UItemTracer* Tracer = Cast<UItemTracer>(Result.GetValue()))
{
Tracer->SetItemLocation(SelfAsObject);
Tracer->OnItemMoved.Broadcast(Tracer); // 广播移动事件
}
}
}
}
InjectPayloadImpl(MoveTemp(Payload));
}
```
**在 Blueprint 中绑定移动事件:**
UI 或任务系统通过获取物品属性包中的 Internal_ItemTracer 对象,绑定其 OnItemMoved 委托来响应物品移动。当容器调用 InjectPayload 时,委托被广播,绑定的监听方收到通知。
**查询位置:**
在 Blueprint 中调用 GetItemLocation 获取物品当前所在 UObject或调用 FindActorInOuterChain 追溯到所属 Actor。
## 用例
- `Plugins/Item/Source/Item/Public/ItemFactory.h:27` -- FOnItemMoved 委托类型声明DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam
- `Plugins/Item/Source/Item/Public/ItemFactory.h:29-57` -- UItemTracer 类定义OnItemMoved 成员 + GetItemLocation / FindActorInOuterChain / SetItemLocation 方法)。
- `Plugins/Item/Source/Item/Private/ItemFactory.cpp:17-22` -- CreateItemInstance 中当 bHasTracer 为 true 时创建 UItemTracer 并添加到属性包。
- `Plugins/Item/Source/Item/Private/ItemContainer.cpp:49` -- InjectPayload NVI 中通过 UInternalItemProperty::ItemTracer() 键名查找 Tracer。
- `Plugins/Item/Source/Item/Private/ItemContainer.cpp:57-60` -- InjectPayload 中 Cast 到 UItemTracer调用 SetItemLocation 更新位置Broadcast OnItemMoved 通知监听方。