87 lines
3.9 KiB
Markdown
87 lines
3.9 KiB
Markdown
|
# Untracked
|
|||
|
|
|||
|
- **功能描述:** 使得TSoftObjectPtr和FSoftObjectPath的软对象引用类型的属性,不跟踪记录资产的 。
|
|||
|
- **使用位置:** UPROPERTY
|
|||
|
- **引擎模块:** Object Property
|
|||
|
- **元数据类型:** bool
|
|||
|
- **限制类型:** TSoftObjectPtr,FSoftObjectPath
|
|||
|
- **常用程度:** ★
|
|||
|
|
|||
|
使得TSoftObjectPtr和FSoftObjectPath的软对象引用类型的属性,不跟踪记录资产的 。
|
|||
|
|
|||
|
一般默认情况,属性上的软对象引用也是会产生资产的引用依赖,虽然在Load本身的时候,不会像硬引用一样也去加载其他软引用对象。但是因为引用关系依然存在,因此在cook的时候,或者资产重定向的时候都会去检查这些软引用对象,确保其也会被cook进去,或者正常的处理。
|
|||
|
|
|||
|
而当你想在属性上记录“引用”一些资产,以便之后加载使用,但是又不想产生真正的资产引用依赖,这个时候就可以用untracked。源码中应用的不多,这是比较稀少的情况下。
|
|||
|
|
|||
|
和transient标记的区别是,transient属性在序列化的时候也不会序列化,因为其ctrl+S保存后重启编辑器会丢失值。transient属性既不产生资产引用关系也序列化保存值,Untracked属性会序列化保存值但不产生资产引用关系。
|
|||
|
|
|||
|
## 测试代码:
|
|||
|
|
|||
|
```cpp
|
|||
|
UCLASS(Blueprintable, BlueprintType)
|
|||
|
class INSIDER_API UMyProperty_Soft :public UDataAsset
|
|||
|
{
|
|||
|
GENERATED_BODY()
|
|||
|
public:
|
|||
|
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
|||
|
TSoftObjectPtr<UStaticMesh> MyStaticMesh;
|
|||
|
|
|||
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (Untracked))
|
|||
|
TSoftObjectPtr<UStaticMesh> MyStaticMeshUntracked;
|
|||
|
|
|||
|
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
|||
|
FSoftObjectPath MySoftMesh;
|
|||
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (Untracked))
|
|||
|
FSoftObjectPath MySoftMeshUntracked;
|
|||
|
|
|||
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Transient)
|
|||
|
TSoftObjectPtr<UStaticMesh> MyStaticMeshTransient;
|
|||
|
};
|
|||
|
```
|
|||
|
|
|||
|
## 蓝图效果:
|
|||
|
|
|||
|
在蓝图中建立一个UMyProperty_Soft DataAsset资产,然后设置其属性值。然后查看其引用的资源,会发现Untracked的属性,其设置的资产并没有出现在引用关系中。当然Transient的属性也不在引用关系中。
|
|||
|
|
|||
|

|
|||
|
|
|||
|
## 原理:
|
|||
|
|
|||
|
Untracked元数据,会设置为ESoftObjectPathCollectType::NeverCollect的选项。继续搜索会发现带有NeverCollect的FSoftObjectPath,其上面的资产package 不会被算到资产引用里,从而不会带到upackage Import表里。源码中有多处地方带有这个NeverCollect 的类似判断。
|
|||
|
|
|||
|
```cpp
|
|||
|
bool FSoftObjectPathThreadContext::GetSerializationOptions(FName& OutPackageName, FName& OutPropertyName, ESoftObjectPathCollectType& OutCollectType, ESoftObjectPathSerializeType& OutSerializeType, FArchive* Archive) const
|
|||
|
{
|
|||
|
#if WITH_EDITOR
|
|||
|
bEditorOnly = Archive->IsEditorOnlyPropertyOnTheStack();
|
|||
|
|
|||
|
static FName UntrackedName = TEXT("Untracked");
|
|||
|
if (CurrentProperty && CurrentProperty->GetOwnerProperty()->HasMetaData(UntrackedName))
|
|||
|
{
|
|||
|
// Property has the Untracked metadata, so set to never collect references if it's higher than NeverCollect
|
|||
|
CurrentCollectType = FMath::Min(ESoftObjectPathCollectType::NeverCollect, CurrentCollectType);
|
|||
|
}
|
|||
|
#endif
|
|||
|
}
|
|||
|
|
|||
|
FArchive& FImportExportCollector::operator<<(FSoftObjectPath& Value)
|
|||
|
{
|
|||
|
FName CurrentPackage;
|
|||
|
FName PropertyName;
|
|||
|
ESoftObjectPathCollectType CollectType;
|
|||
|
ESoftObjectPathSerializeType SerializeType;
|
|||
|
FSoftObjectPathThreadContext& ThreadContext = FSoftObjectPathThreadContext::Get();
|
|||
|
ThreadContext.GetSerializationOptions(CurrentPackage, PropertyName, CollectType, SerializeType, this);
|
|||
|
|
|||
|
if (CollectType != ESoftObjectPathCollectType::NeverCollect && CollectType != ESoftObjectPathCollectType::NonPackage)
|
|||
|
{
|
|||
|
FName PackageName = Value.GetLongPackageFName();
|
|||
|
if (PackageName != RootPackageName && !PackageName.IsNone())
|
|||
|
{
|
|||
|
AddImport(Value, CollectType);
|
|||
|
}
|
|||
|
}
|
|||
|
return *this;
|
|||
|
}
|
|||
|
```
|