4.6 KiB
4.6 KiB
NonPIEDuplicateTransient
-
功能描述: 在对象复制的时候,且在不是PIE的场合,忽略该属性。
-
元数据类型: bool
-
引擎模块: Serialization
-
作用机制: 在PropertyFlags中加入CPF_NonPIEDuplicateTransient
-
常用程度: ★
在对象复制的时候,且在不是PIE的场合,忽略该属性。
- DuplicateTransient和NonPIEDuplicateTransient的区别是,前者在任何情况的对象复制时都忽略该属性,而后者在PIE的时候(也是在发生对象复制过程)依然会复制该属性,其他情况下的复制和前者行为一致。
- PIE的时候本质就是把当前的编辑World里Actor复制一份到PIE的世界里,会触发Actor的复制。
示例代码:
准备了一份DataAsset和Actor来分别验证复制行为的不同。
UCLASS(Blueprintable, BlueprintType)
class INSIDER_API UMyProperty_Serialization :public UDataAsset
{
public:
GENERATED_BODY()
public:
UPROPERTY(EditAnywhere, BlueprintReadWrite)
int32 MyInt_Default = 123;
//PropertyFlags: CPF_Edit | CPF_BlueprintVisible | CPF_ZeroConstructor | CPF_Transient | CPF_IsPlainOldData | CPF_NoDestructor | CPF_HasGetValueTypeHash | CPF_NativeAccessSpecifierPublic
UPROPERTY(EditAnywhere, BlueprintReadWrite, Transient)
int32 MyInt_Transient = 123;
//PropertyFlags: CPF_Edit | CPF_BlueprintVisible | CPF_ZeroConstructor | CPF_DuplicateTransient | CPF_IsPlainOldData | CPF_NoDestructor | CPF_HasGetValueTypeHash | CPF_NativeAccessSpecifierPublic
UPROPERTY(EditAnywhere, BlueprintReadWrite, DuplicateTransient)
int32 MyInt_DuplicateTransient = 123;
//PropertyFlags: CPF_Edit | CPF_BlueprintVisible | CPF_ZeroConstructor | CPF_IsPlainOldData | CPF_NoDestructor | CPF_NonPIEDuplicateTransient | CPF_HasGetValueTypeHash | CPF_NativeAccessSpecifierPublic
UPROPERTY(EditAnywhere, BlueprintReadWrite, NonPIEDuplicateTransient)
int32 MyInt_NonPIEDuplicateTransient = 123;
};
UCLASS(Blueprintable, BlueprintType)
class INSIDER_API AMyProperty_Serialization_TestActor :public AActor
{
public:
GENERATED_BODY()
protected:
UPROPERTY(EditAnywhere, BlueprintReadWrite)
int32 MyInt_Default = 123;
//PropertyFlags: CPF_Edit | CPF_BlueprintVisible | CPF_ZeroConstructor | CPF_Transient | CPF_IsPlainOldData | CPF_NoDestructor | CPF_HasGetValueTypeHash | CPF_NativeAccessSpecifierPublic
UPROPERTY(EditAnywhere, BlueprintReadWrite, Transient)
int32 MyInt_Transient = 123;
//PropertyFlags: CPF_Edit | CPF_BlueprintVisible | CPF_ZeroConstructor | CPF_DuplicateTransient | CPF_IsPlainOldData | CPF_NoDestructor | CPF_HasGetValueTypeHash | CPF_NativeAccessSpecifierPublic
UPROPERTY(EditAnywhere, BlueprintReadWrite, DuplicateTransient)
int32 MyInt_DuplicateTransient = 123;
UPROPERTY(EditAnywhere, BlueprintReadWrite, NonPIEDuplicateTransient)
int32 MyInt_NonPIEDuplicateTransient = 123;
};
示例效果:
在对资产进行Duplidate的时候,发生DuplicateAsset然后DuplicateObject,这个时候PortFlags=PPF_Duplicate,然后会触发ShouldSerializeValue进行判断。这个时候会跳过该属性。
可以看到NonPIEDuplicateTransient并不会被复制。
在点击PIE的时候,可以看到NonPIEDuplicateTransient这个时候却是会复制值过去了。这是因为这个时候PortFlags=PPF_DuplicateForPIE&PPF_Duplicate
结论是用于一些Cache数据,在复制的时候并不需要序列化复制,这样可以阻止两个不同的Actor采用同一份计算后的临时数据。但是又可以在PIE的时候,让Actor各自采用自己的一份数据,因为PIE的时候,本质就是把当前的编辑World里Actor复制一份到PIE的世界里,会触发Actor的复制。
原理:
在文本导出的的时候,在不是PIE里的复制的时候,不序列化该属性。
bool FProperty::ShouldPort( uint32 PortFlags/*=0*/ ) const
{
// if we're not copying for PIE and NonPIETransient is set, don't export
if (!(PortFlags & PPF_DuplicateForPIE) && HasAnyPropertyFlags(CPF_NonPIEDuplicateTransient))
{
return false;
}
}
在二进制序列化的时候:
只有在PPF_Duplicate生效的时候,(DuplicateObject?或者资产复制),才会跳过该属性。但是在PIE的时候,又要继续序列化。
bool FProperty::ShouldSerializeValue(FArchive& Ar) const
{
// Skip properties marked NonPIEDuplicateTransient when duplicating, but not when we're duplicating for PIE
if ((PropertyFlags & CPF_NonPIEDuplicateTransient) && !(Ar.GetPortFlags() & PPF_DuplicateForPIE) && (Ar.GetPortFlags() & PPF_Duplicate))
{
return false;
}
}