# BlueprintCompilerGeneratedDefaults - **功能描述:** 指定该属性的值是编译器生成的,因此在编译后无需复制,可以加速一些编译性能。 - **使用位置:** UPROPERTY - **引擎模块:** AnimationGraph - **元数据类型:** bool - **限制类型:** FAnimNode里的属性 指定该属性的值是编译器生成的,因此在编译后无需复制,可以加速一些编译性能。 在源码里寻找例子,可以看到基本是在FAnimNode下的属性在使用。在动画蓝图编译后,会调用UEngine::CopyPropertiesForUnrelatedObjects来把之前编译的旧对象里的值复制到新对象,其中FCopyPropertiesForUnrelatedObjectsParams的bSkipCompilerGeneratedDefaults决定是否要赋值这个属性的值。如果有标上这个值,就说明不要复制。这个值会在别的地方由编译器来填充值。 UAnimGraphNode_Base::OnProcessDuringCompilation函数就是编译后回调的函数。 ## 测试代码: ```cpp USTRUCT(BlueprintInternalUseOnly) struct INSIDER_API FAnimNode_MyCompilerDefaults : public FAnimNode_Base { GENERATED_USTRUCT_BODY() public: UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=Links) FPoseLink Source; public: UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = CompilerDefaultsTest) FString MyString; UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = CompilerDefaultsTest, meta = (BlueprintCompilerGeneratedDefaults)) FString MyString_CompilerDefaults; }; UCLASS() class INSIDEREDITOR_API UAnimGraphNode_MyCompilerDefaults : public UAnimGraphNode_Base { GENERATED_UCLASS_BODY() public: ~UAnimGraphNode_MyCompilerDefaults(); UPROPERTY(EditAnywhere, Category = Settings) FAnimNode_MyCompilerDefaults Node; protected: virtual void OnProcessDuringCompilation(IAnimBlueprintCompilationContext& InCompilationContext, IAnimBlueprintGeneratedClassCompiledData& OutCompiledData) { Node.MyString=TEXT("This is generated by compiler."); Node.MyString_CompilerDefaults=TEXT("This is generated by compiler."); } }; ``` ## 测试效果: 这个因为是序列化的过程,因此并没有直观的示意图。 可验证的结果是在FCPFUOWriter::ShouldSkipProperty可以见到MyString_CompilerDefaults属性跳过了复制。 ## 原理: 蓝图编译的过程,核心思想是生成一个新的Graph对象,然后把上一次编译的结果对象里的属性和只对象复制到这个新的对象里去。这一步操作是用UEngine::CopyPropertiesForUnrelatedObjects来完成的,再内部会继续用FCPFUOWriter::ShouldSkipProperty来判断是否该复制某个属性。而对于一些属性的值只是由编译器生成的临时值,反正下一次编译也会再生成,因此就不需要复制了,标上之后可以略微加速一些性能,虽然其实也不多。 ```cpp void UK2Node_PropertyAccess::CreateClassVariablesFromBlueprint(IAnimBlueprintVariableCreationContext& InCreationContext) { GeneratedPropertyName = NAME_None; const bool bRequiresCachedVariable = !bWasResolvedThreadSafe || UAnimBlueprintExtension_PropertyAccess::ContextRequiresCachedVariable(ContextId); if(ResolvedPinType != FEdGraphPinType() && ResolvedPinType.PinCategory != UEdGraphSchema_K2::PC_Wildcard && bRequiresCachedVariable) { // Create internal generated destination property (only if we were not identified as thread safe) if(FProperty* DestProperty = InCreationContext.CreateUniqueVariable(this, ResolvedPinType)) { GeneratedPropertyName = DestProperty->GetFName(); DestProperty->SetMetaData(TEXT("BlueprintCompilerGeneratedDefaults"), TEXT("true")); } } } /* Serializes and stores property data from a specified 'source' object. Only stores data compatible with a target destination object. */ struct FCPFUOWriter : public FObjectWriter, public FCPFUOArchive { #if WITH_EDITOR virtual bool ShouldSkipProperty(const class FProperty* InProperty) const override { return (bSkipCompilerGeneratedDefaults && InProperty->HasMetaData(BlueprintCompilerGeneratedDefaultsName)); } #endif } ```