文章目录
- 概要
- UE Get节点有哪些常见的应用场景
- 相关源码
概要
UE Get节点在Unreal Engine的蓝图系统中用于获取变量的值。这个节点通常用于从变量中读取数据,以便在游戏的逻辑流程中使用。
要使用Get节点,你首先需要有一个已经定义的变量。然后,在蓝图编辑器中,你可以通过右键点击空白处,选择“添加节点” -> “变量” -> “Get”来创建一个Get节点。在弹出的窗口中,你可以选择需要获取的变量。一旦创建了Get节点,你可以将其拖拽到蓝图的适当位置,并连接它到需要使用该变量值的其他节点。
需要注意的是,Get节点只是获取变量的值,而不会修改它。如果你想修改变量的值,你应该使用Set节点。
Get节点的输出可以用于驱动蓝图中的其他逻辑或操作。例如,你可以使用Get节点获取一个游戏对象的位置,然后根据这个位置来执行某些动作或决策。
总的来说,UE Get节点是Unreal Engine蓝图系统中用于读取变量值的重要工具,它使得开发者能够灵活地获取和使用游戏中的数据。
UE Get节点有哪些常见的应用场景
UE Get节点在Unreal Engine的蓝图系统中主要用于获取变量的值,这些变量可以是游戏对象的状态、属性、配置参数等。由于Get节点能够动态地获取变量的值,因此它在多种场景中都有广泛的应用。以下是一些UE Get节点常见的应用场景:
动态调整游戏对象的行为:通过Get节点获取游戏对象的某些属性(如位置、速度、旋转等),然后根据这些属性的值动态调整游戏对象的行为。例如,根据玩家的位置调整敌人的攻击策略,或者根据物体的速度调整其移动方式。
实现条件判断和分支逻辑:结合Branch节点或其他控制流节点,使用Get节点获取变量的值来进行条件判断。根据判断结果,执行不同的逻辑分支。这在构建复杂的游戏逻辑和交互中非常常见。
同步多个游戏对象的状态:在某些情况下,你可能需要确保多个游戏对象保持同步的状态。通过Get节点获取一个游戏对象的状态,并使用Set节点将其应用到其他游戏对象上,可以实现状态的同步和一致性。
响应用户输入和事件:在事件驱动的游戏逻辑中,Get节点可以用于获取用户输入或事件触发的变量值。例如,当用户按下某个按钮时,通过Get节点获取按钮状态的值,并据此执行相应的操作或响应。
配置管理和动态加载:在游戏开发过程中,可能需要根据不同的配置或参数来调整游戏的行为。通过Get节点获取配置文件或参数表中的变量值,可以实现游戏行为的动态加载和调整。
需要注意的是,虽然Get节点在多种场景中都有应用,但在使用时也需要注意数据的时效性和准确性。确保你获取的变量值是最新且正确的,以避免逻辑错误或不一致的行为。
总的来说,UE Get节点是Unreal Engine蓝图系统中非常重要的一个节点类型,它使得开发者能够灵活地获取游戏中的数据,并根据这些数据实现各种复杂的逻辑和交互。
相关源码
源码文件:
K2Node_VariableGet.h
K2Node_VariableGet.cpp
相关类:
FKCHandler_VariableGet
K2Node_VariableGetImpl
#include "K2Node_VariableGet.h"
#include "UObject/UObjectHash.h"
#include "UObject/PropertyPortFlags.h"
#include "Kismet/KismetSystemLibrary.h"
#include "Framework/Commands/UIAction.h"
#include "ToolMenus.h"
#include "EdGraph/EdGraph.h"
#include "EdGraphSchema_K2.h"
#include "K2Node_CallFunction.h"
#include "K2Node_IfThenElse.h"
#include "Kismet2/BlueprintEditorUtils.h"
#include "KismetCompilerMisc.h"
#include "KismetCompiler.h"
#include "ScopedTransaction.h"//
// FKCHandler_VariableGet#define LOCTEXT_NAMESPACE "K2Node"class FKCHandler_VariableGet : public FNodeHandlingFunctor
{
public:FKCHandler_VariableGet(FKismetCompilerContext& InCompilerContext): FNodeHandlingFunctor(InCompilerContext){}virtual void RegisterNet(FKismetFunctionContext& Context, UEdGraphPin* Net) override{// This net is a variable readResolveAndRegisterScopedTerm(Context, Net, Context.VariableReferences);}virtual void RegisterNets(FKismetFunctionContext& Context, UEdGraphNode* Node) override{UK2Node_Variable* VarNode = Cast<UK2Node_Variable>(Node);if (VarNode){VarNode->CheckForErrors(CompilerContext.GetSchema(), Context.MessageLog);// Report an error that the local variable could not be foundif(VarNode->VariableReference.IsLocalScope() && VarNode->GetPropertyForVariable() == NULL){FFormatNamedArguments Args;Args.Add(TEXT("VariableName"), FText::FromName(VarNode->VariableReference.GetMemberName()));if(VarNode->VariableReference.GetMemberScopeName() != Context.Function->GetName()){Args.Add(TEXT("ScopeName"), FText::FromString(VarNode->VariableReference.GetMemberScopeName()));CompilerContext.MessageLog.Warning(*FText::Format(LOCTEXT("LocalVariableNotFoundInScope_Error", "Unable to find local variable with name '{VariableName}' for @@, scope expected: @@, scope found: {ScopeName}"), Args).ToString(), Node, Node->GetGraph());}else{CompilerContext.MessageLog.Warning(*FText::Format(LOCTEXT("LocalVariableNotFound_Error", "Unable to find local variable with name '{VariableName}' for @@"), Args).ToString(), Node);}}}FNodeHandlingFunctor::RegisterNets(Context, Node);}
};namespace K2Node_VariableGetImpl
{/*** Shared utility method for retrieving a UK2Node_VariableGet's bare tooltip.* * @param VarName The name of the variable that the node represents.* @return A formatted text string, describing what the VariableGet node does.*/static FText GetBaseTooltip(FName VarName);
}static FText K2Node_VariableGetImpl::GetBaseTooltip(FName VarName)
{FFormatNamedArguments Args;Args.Add(TEXT("VarName"), FText::FromName(VarName));return FText::Format(LOCTEXT("GetVariableTooltip", "Read the value of variable {VarName}"), Args);}UK2Node_VariableGet::UK2Node_VariableGet(const FObjectInitializer& ObjectInitializer): Super(ObjectInitializer), bIsPureGet(true)
{
}void UK2Node_VariableGet::CreateNonPurePins(TArray<UEdGraphPin*>* InOldPinsPtr)
{const UEdGraphSchema_K2* K2Schema = Cast<UEdGraphSchema_K2>(GetSchema());check(K2Schema != nullptr);if (!K2Schema->DoesGraphSupportImpureFunctions(GetGraph())){bIsPureGet = true;}if (!bIsPureGet){FEdGraphPinType PinType;FProperty* VariableProperty = GetPropertyForVariable();// We need the pin's type, to both see if it's an array and if it is of the correct types to remain an impure nodeif (VariableProperty){K2Schema->ConvertPropertyToPinType(GetPropertyForVariable(), PinType);}// If there is no property and we are given some old pins to look at, find the old value pin and use the type there// This allows nodes to be pasted into other BPs without access to the propertyelse if (InOldPinsPtr){// find old variable pin and use the type.const FName PinName = GetVarName();for (const UEdGraphPin* Pin : *InOldPinsPtr){if (Pin && PinName == Pin->PinName){PinType = Pin->PinType;break;}}}if (IsValidTypeForNonPure(PinType)){// Input - Execution PinCreatePin(EGPD_Input, UEdGraphSchema_K2::PC_Exec, UEdGraphSchema_K2::PN_Execute);// Output - Execution PinsUEdGraphPin* ValidPin = CreatePin(EGPD_Output, UEdGraphSchema_K2::PC_Exec, UEdGraphSchema_K2::PN_Then);ValidPin->PinFriendlyName = LOCTEXT("Valid", "Is Valid");UEdGraphPin* InvalidPin = CreatePin(EGPD_Output, UEdGraphSchema_K2::PC_Exec, UEdGraphSchema_K2::PN_Else);InvalidPin->PinFriendlyName = LOCTEXT("Invalid", "Is Not Valid");}else{bIsPureGet = true;}}
}void UK2Node_VariableGet::AllocateDefaultPins()
{if(GetVarName() != NAME_None){CreateNonPurePins(nullptr);if(CreatePinForVariable(EGPD_Output)){CreatePinForSelf();}}Super::AllocateDefaultPins();
}void UK2Node_VariableGet::ReallocatePinsDuringReconstruction(TArray<UEdGraphPin*>& OldPins)
{if(GetVarName() != NAME_None){CreateNonPurePins(&OldPins);if(!CreatePinForVariable(EGPD_Output)){if(!RecreatePinForVariable(EGPD_Output, OldPins)){return;}}CreatePinForSelf();RestoreSplitPins(OldPins);}
}FText UK2Node_VariableGet::GetPropertyTooltip(FProperty const* VariableProperty)
{FName VarName = NAME_None;if (VariableProperty != nullptr){VarName = VariableProperty->GetFName();UClass* SourceClass = VariableProperty->GetOwnerClass();// discover if the variable property is a non blueprint user variablebool const bIsNativeVariable = (SourceClass != nullptr) && (SourceClass->ClassGeneratedBy == nullptr);FText SubTooltip;if (bIsNativeVariable){FText const PropertyTooltip = VariableProperty->GetToolTipText();if (!PropertyTooltip.IsEmpty()){// See if the native property has a tooltipSubTooltip = PropertyTooltip;FString TooltipName = FString::Printf(TEXT("%s.%s"), *VarName.ToString(), *FBlueprintMetadata::MD_Tooltip.ToString());FText::FindText(*VariableProperty->GetFullGroupName(true), *TooltipName, SubTooltip);}}else if (SourceClass){if (UBlueprint* VarBlueprint = Cast<UBlueprint>(SourceClass->ClassGeneratedBy)){FString UserTooltipData;if (FBlueprintEditorUtils::GetBlueprintVariableMetaData(VarBlueprint, VarName, VariableProperty->GetOwnerStruct(), FBlueprintMetadata::MD_Tooltip, UserTooltipData)){SubTooltip = FText::FromString(UserTooltipData);}}}if (!SubTooltip.IsEmpty()){FFormatNamedArguments Args;Args.Add(TEXT("VarName"), FText::FromName(VarName));Args.Add(TEXT("PropertyTooltip"), SubTooltip);return FText::Format(LOCTEXT("GetVariableProperty_Tooltip", "Read the value of variable {VarName}\n{PropertyTooltip}"), Args);}}return K2Node_VariableGetImpl::GetBaseTooltip(VarName);
}FText UK2Node_VariableGet::GetBlueprintVarTooltip(FBPVariableDescription const& VarDesc)
{int32 const MetaIndex = VarDesc.FindMetaDataEntryIndexForKey(FBlueprintMetadata::MD_Tooltip);bool const bHasTooltipData = (MetaIndex != INDEX_NONE);if (bHasTooltipData){FString UserTooltipData = VarDesc.GetMetaData(FBlueprintMetadata::MD_Tooltip);FFormatNamedArguments Args;Args.Add(TEXT("VarName"), FText::FromName(VarDesc.VarName));Args.Add(TEXT("UserTooltip"), FText::FromString(UserTooltipData));return FText::Format(LOCTEXT("GetBlueprintVariable_Tooltip", "Read the value of variable {VarName}\n{UserTooltip}"), Args);}return K2Node_VariableGetImpl::GetBaseTooltip(VarDesc.VarName);
}FText UK2Node_VariableGet::GetTooltipText() const
{if (CachedTooltip.IsOutOfDate(this)){if (FProperty* Property = GetPropertyForVariable()){CachedTooltip.SetCachedText(GetPropertyTooltip(Property), this);}else if (FBPVariableDescription const* VarDesc = GetBlueprintVarDescription()){CachedTooltip.SetCachedText(GetBlueprintVarTooltip(*VarDesc), this);}else{CachedTooltip.SetCachedText(K2Node_VariableGetImpl::GetBaseTooltip(GetVarName()), this);}}return CachedTooltip;
}FText UK2Node_VariableGet::GetNodeTitle(ENodeTitleType::Type TitleType) const
{// If there is only one variable being read, the title can be made the variable nameFName OutputPinName;int32 NumOutputsFound = 0;for (int32 PinIndex = 0; PinIndex < Pins.Num(); ++PinIndex){UEdGraphPin* Pin = Pins[PinIndex];// The following code is to attempt to log info related to UE-19729if (TitleType == ENodeTitleType::ListView){if (UEdGraph* Graph = Cast<UEdGraph>(GetOuter())){FString VariableName = GetVarNameString();FString BlueprintPath = FBlueprintEditorUtils::FindBlueprintForGraph(Graph)->GetPathName();FString SetupStyle = bIsPureGet? TEXT("pure") : TEXT("validated");FString VariableResolves = (VariableReference.ResolveMember<FProperty>(GetBlueprintClassFromNode()) != nullptr)? TEXT("resolves") : TEXT("does not resolve");checkf(Pin, TEXT("Get node for variable '%s' in Blueprint '%s' which is setup as %s and has %d pins. Variable %s"), *VariableName, *BlueprintPath, *SetupStyle, Pins.Num(), *VariableResolves);}}if (Pin->Direction == EGPD_Output){++NumOutputsFound;OutputPinName = Pin->PinName;}}if (NumOutputsFound != 1){return LOCTEXT("Get", "Get");}else if (CachedNodeTitle.IsOutOfDate(this)){FFormatNamedArguments Args;Args.Add(TEXT("PinName"), FText::FromName(OutputPinName));// FText::Format() is slow, so we cache this to save on performanceCachedNodeTitle.SetCachedText(FText::Format(LOCTEXT("GetPinName", "Get {PinName}"), Args), this);}return CachedNodeTitle;
}FNodeHandlingFunctor* UK2Node_VariableGet::CreateNodeHandler(FKismetCompilerContext& CompilerContext) const
{return new FKCHandler_VariableGet(CompilerContext);
}bool UK2Node_VariableGet::IsValidTypeForNonPure(const FEdGraphPinType& InPinType)
{return !InPinType.IsContainer() && (InPinType.PinCategory == UEdGraphSchema_K2::PC_Object || InPinType.PinCategory == UEdGraphSchema_K2::PC_Class || InPinType.PinCategory == UEdGraphSchema_K2::PC_SoftObject || InPinType.PinCategory == UEdGraphSchema_K2::PC_SoftClass);
}void UK2Node_VariableGet::GetNodeContextMenuActions(UToolMenu* Menu, UGraphNodeContextMenuContext* Context) const
{Super::GetNodeContextMenuActions(Menu, Context);const UEdGraphPin* ValuePin = GetValuePin();if (ValuePin && IsValidTypeForNonPure(ValuePin->PinType)){{FText MenuEntryTitle;FText MenuEntryTooltip;bool bCanTogglePurity = true;auto CanExecutePurityToggle = [](bool const bInCanTogglePurity)->bool{return bInCanTogglePurity;};if (bIsPureGet){MenuEntryTitle = LOCTEXT("ConvertToImpureGetTitle", "Convert to Validated Get");MenuEntryTooltip = LOCTEXT("ConvertToImpureGetTooltip", "Adds in branching execution pins so that you can separately handle when the returned value is valid/invalid.");const UEdGraphSchema_K2* K2Schema = Cast<UEdGraphSchema_K2>(GetSchema());check(K2Schema != nullptr);bCanTogglePurity = K2Schema->DoesGraphSupportImpureFunctions(GetGraph());if (!bCanTogglePurity){MenuEntryTooltip = LOCTEXT("CannotMakeImpureGetTooltip", "This graph does not support impure calls!");}}else{MenuEntryTitle = LOCTEXT("ConvertToPureGetTitle", "Convert to pure Get");MenuEntryTooltip = LOCTEXT("ConvertToPureGetTooltip", "Removes the execution pins to make the node more versatile.");}FToolMenuSection& Section = Menu->AddSection("K2NodeVariableGet", LOCTEXT("VariableGetHeader", "Variable Get"));Section.AddMenuEntry("TogglePurity",MenuEntryTitle,MenuEntryTooltip,FSlateIcon(),FUIAction(FExecuteAction::CreateUObject(const_cast<UK2Node_VariableGet*>(this), &UK2Node_VariableGet::TogglePurity),FCanExecuteAction::CreateStatic(CanExecutePurityToggle, bCanTogglePurity && !Context->bIsDebugging),FIsActionChecked()));}}
}void UK2Node_VariableGet::TogglePurity()
{FText TransactionTitle;if(!bIsPureGet){TransactionTitle = LOCTEXT("TogglePureGet", "Convert to Pure Get");}else{TransactionTitle = LOCTEXT("ToggleImpureGet", "Convert to Impure Get");}const FScopedTransaction Transaction( TransactionTitle );Modify();SetPurity(!bIsPureGet);
}void UK2Node_VariableGet::SetPurity(bool bNewPurity)
{if (bNewPurity != bIsPureGet){bIsPureGet = bNewPurity;bool const bHasBeenConstructed = (Pins.Num() > 0);if (bHasBeenConstructed){ReconstructNode();}}
}void UK2Node_VariableGet::ValidateNodeDuringCompilation(FCompilerResultsLog& MessageLog) const
{Super::ValidateNodeDuringCompilation(MessageLog);// Some expansions, such as timelines, will create gets for non-blueprint visible properties, and we don't want to validate against thatif (!IsIntermediateNode()){if (FProperty* Property = GetPropertyForVariable()){const FBlueprintEditorUtils::EPropertyReadableState PropertyReadableState = FBlueprintEditorUtils::IsPropertyReadableInBlueprint(GetBlueprint(), Property);if (PropertyReadableState != FBlueprintEditorUtils::EPropertyReadableState::Readable){FFormatNamedArguments Args;if (UObject* Class = Property->GetOwner<UObject>()){Args.Add(TEXT("VariableName"), FText::AsCultureInvariant(FString::Printf(TEXT("%s.%s"), *Class->GetName(), *Property->GetName())));}else{Args.Add(TEXT("VariableName"), FText::AsCultureInvariant(Property->GetName()));}if (PropertyReadableState == FBlueprintEditorUtils::EPropertyReadableState::NotBlueprintVisible){// UE_DEPRECATED(4.17) ... make this an errorMessageLog.Warning(*FText::Format(LOCTEXT("UnableToGet_NotVisible", "{VariableName} is not blueprint visible (BlueprintReadOnly or BlueprintReadWrite). Please fix mark up or cease accessing as this will be made an error in a future release. @@"), Args).ToString(), this);}else if (PropertyReadableState == FBlueprintEditorUtils::EPropertyReadableState::Private){// UE_DEPRECATED(4.17) ... make this an errorMessageLog.Warning(*FText::Format(LOCTEXT("UnableToGet_ReadOnly", "{VariableName} is private and not accessible in this context. Please fix mark up or cease accessing as this will be an error in a future release. @@"), Args).ToString(), this);}else{check(false);}}}}
}void UK2Node_VariableGet::ExpandNode(class FKismetCompilerContext& CompilerContext, UEdGraph* SourceGraph)
{Super::ExpandNode(CompilerContext, SourceGraph);FProperty* VariableProperty = GetPropertyForVariable();UK2Node_VariableGet* VariableGetNode = this;// Do not attempt to expand the node when not a pure get nor when there is no property. Normal compilation error detection will detect the missing property.if (!bIsPureGet && VariableProperty){UEdGraphPin* ValuePin = GetValuePin();// Impure Get nodes convert into three nodes:// 1. A pure Get node// 2. An IsValid node// 3. A Branch node (only impure part)// Create the pure Get nodeVariableGetNode = CompilerContext.SpawnIntermediateNode<UK2Node_VariableGet>(this, SourceGraph);VariableGetNode->VariableReference = VariableReference;VariableGetNode->AllocateDefaultPins();CompilerContext.MessageLog.NotifyIntermediateObjectCreation(VariableGetNode, this);// Move pin links from Get node we are expanding, to the new pure one we've createdCompilerContext.MovePinLinksToIntermediate(*ValuePin, *VariableGetNode->GetValuePin());if (!VariableReference.IsLocalScope()){CompilerContext.MovePinLinksToIntermediate(*FindPin(UEdGraphSchema_K2::PN_Self), *VariableGetNode->FindPin(UEdGraphSchema_K2::PN_Self));}// Create the IsValid nodeUK2Node_CallFunction* IsValidFunction = CompilerContext.SpawnIntermediateNode<UK2Node_CallFunction>(this, SourceGraph);// Based on if the type is an "Object" or a "Class" changes which function to useif (ValuePin->PinType.PinCategory == UEdGraphSchema_K2::PC_Object){IsValidFunction->SetFromFunction(UKismetSystemLibrary::StaticClass()->FindFunctionByName(GET_MEMBER_NAME_CHECKED(UKismetSystemLibrary, IsValid)));}else if (ValuePin->PinType.PinCategory == UEdGraphSchema_K2::PC_Class){IsValidFunction->SetFromFunction(UKismetSystemLibrary::StaticClass()->FindFunctionByName(GET_MEMBER_NAME_CHECKED(UKismetSystemLibrary, IsValidClass)));}else if (ValuePin->PinType.PinCategory == UEdGraphSchema_K2::PC_SoftObject){IsValidFunction->SetFromFunction(UKismetSystemLibrary::StaticClass()->FindFunctionByName(GET_MEMBER_NAME_CHECKED(UKismetSystemLibrary, IsValidSoftObjectReference)));}else if (ValuePin->PinType.PinCategory == UEdGraphSchema_K2::PC_SoftClass){IsValidFunction->SetFromFunction(UKismetSystemLibrary::StaticClass()->FindFunctionByName(GET_MEMBER_NAME_CHECKED(UKismetSystemLibrary, IsValidSoftClassReference)));}IsValidFunction->AllocateDefaultPins();CompilerContext.MessageLog.NotifyIntermediateObjectCreation(IsValidFunction, this);// Connect the value pin from the new Get node to the IsValidUEdGraphPin* ObjectPin = IsValidFunction->Pins[1];check(ObjectPin->Direction == EGPD_Input);ObjectPin->MakeLinkTo(VariableGetNode->GetValuePin());// Create the Branch nodeUK2Node_IfThenElse* BranchNode = CompilerContext.SpawnIntermediateNode<UK2Node_IfThenElse>(this, SourceGraph);BranchNode->AllocateDefaultPins();CompilerContext.MessageLog.NotifyIntermediateObjectCreation(BranchNode, this);// Connect the bool output pin from IsValid node to the Branch nodeUEdGraphPin* BoolPin = IsValidFunction->Pins[2];check(BoolPin->Direction == EGPD_Output);BoolPin->MakeLinkTo(BranchNode->GetConditionPin());// Connect the Branch node to the input of the impure Get nodeCompilerContext.MovePinLinksToIntermediate(*GetExecPin(), *BranchNode->GetExecPin());// Move the two Branch pins to the Branch nodeCompilerContext.MovePinLinksToIntermediate(*FindPin(UEdGraphSchema_K2::PN_Then), *BranchNode->FindPin(UEdGraphSchema_K2::PN_Then));CompilerContext.MovePinLinksToIntermediate(*FindPin(UEdGraphSchema_K2::PN_Else), *BranchNode->FindPin(UEdGraphSchema_K2::PN_Else));BreakAllNodeLinks();}// If property has a BlueprintGetter accessor, then replace the variable get node with a call functionif (VariableProperty){const FString& GetFunctionName = VariableProperty->GetMetaData(FBlueprintMetadata::MD_PropertyGetFunction);if (!GetFunctionName.IsEmpty()){UClass* OwnerClass = VariableProperty->GetOwnerClass();UFunction* GetFunction = OwnerClass->FindFunctionByName(*GetFunctionName);check(GetFunction);UK2Node_CallFunction* CallFuncNode = CompilerContext.SpawnIntermediateNode<UK2Node_CallFunction>(this, SourceGraph);CallFuncNode->SetFromFunction(GetFunction);CallFuncNode->AllocateDefaultPins();const UEdGraphSchema_K2* K2Schema = CompilerContext.GetSchema();// Move Self pin connectionsCompilerContext.MovePinLinksToIntermediate(*K2Schema->FindSelfPin(*this, EGPD_Input), *K2Schema->FindSelfPin(*CallFuncNode, EGPD_Input));// Move Value pin connectionsCompilerContext.MovePinLinksToIntermediate(*GetValuePin(), *CallFuncNode->GetReturnValuePin());}}
}void UK2Node_VariableGet::Serialize(FArchive& Ar)
{// The following code is to attempt to log info related to UE-19729if (Ar.IsSaving() && Ar.IsPersistent()){uint32 PortFlagsToSkip = PPF_Duplicate | PPF_DuplicateForPIE;if (!(Ar.GetPortFlags() & PortFlagsToSkip)){if (UEdGraph* Graph = Cast<UEdGraph>(GetOuter())){if (UBlueprint* Blueprint = FBlueprintEditorUtils::FindBlueprintForGraph(Graph)){if (!Blueprint->bBeingCompiled){// The following line may spur the crash noted in UE-19729 and will confirm that the crash happens before the FiB gather.GetNodeTitle(ENodeTitleType::ListView);}}}}}Super::Serialize(Ar);
}#undef LOCTEXT_NAMESPACE