unreal自定义蓝图节点1
前提配置因为蓝图的节点是仅仅在Editor中使用的,并不需要打包的,为了和项目的代码做好区分处理,所以我使用了module的形式去处理!
module创建
现在是我们希望在Editor的模块下创建自定义的蓝图节点,该节点调用的是运行时的节点! 我们需要在module声明中将该模块改为UncookedOnly(Editor也可以!)
"Modules": [
...
{
"Name": "MyEditorTools",
"Type": "UncookedOnly",
"LoadingPhase": "Default",
"AdditionalDependencies": [
"UnrealGameDemo"
]
}
]在 MyEditorTools.Build.cs 中添加一些必须的依赖,要不然在后续的使用和编译中会有报错!
[*]KismetCompiler
无法解析的外部符号 "declspec(dllimport) public: struct FPinConnectionResponse cdecl FKismetCompilerContext::MovePinLinksToIntermediate(class UEdGraphPin &,class UEdGraphPin &)" (imp_?MovePinLinksToIntermediate@FKismetCompilerContext@@QEAA?AUFPinConnectionResponse@@AEAVUEdGraphPin@@0@Z),函数 "public: virtual void cdecl UCustomNode::ExpandNode(class FKismetCompilerContext &,class UEdGraph *)" (?ExpandNode@UCustomNode@@UEAAXAEAVFKismetCompilerContext@@PEAVUEdGraph@@@Z) 中引用了该符号
[*]BlueprintGraph
无法解析的外部符号 "declspec(dllimport) public: cdecl FBlueprintNodeSignature::FBlueprintNodeSignature(class TSubclassOf)" (imp_??0FBlueprintNodeSignature@@QEAA@V?$TSubclassOf@VUEdGraphNode@@@@@Z),函数 "public: virtual struct FBlueprintNodeSignature cdecl UK2Node::GetSignature(void)const " (?GetSignature@UK2Node@@UEBA?AUFBlueprintNodeSignature@@XZ) 中引用了该符号
[*]UnrealEd
无法解析的外部符号 "declspec(dllimport) public: void cdecl FCompilerResultsLog::NotifyIntermediateObjectCreation(class UObject ,class UObject )" (imp_?NotifyIntermediateObjectCreation@FCompilerResultsLog@@QEAAXPEAVUObject@@0@Z),函数 "public: virtual void cdecl UCustomNode::ExpandNode(class FKismetCompilerContext &,class UEdGraph *)" (?ExpandNode@UCustomNode@@UEAAXAEAVFKismetCompilerContext@@PEAVUEdGraph@@@Z) 中引用了该符号PrivateDependencyModuleNames.AddRange(new string[]{"KismetCompiler", "BlueprintGraph", "UnrealEd"});
具体的蓝图节点实现
[*]直接使用UFUNCTION
[*]自定义蓝图节点
直接使用UFUNCTION
UCLASS()
class UNREALGAMEDEMO_API UCustomRunningNode : public UObject
{
public:
GENERATED_BODY()
UFUNCTION(BlueprintCallable, Category="Custom|CustomRunningNode", meta=(ToolTip="this is a tooltip"))
static void TestBlueprintNode1(FString arg1)
{
UE_LOG(LogUnrealGameDemo, Display, TEXT("UCustomRunningNode::TestBlueprintNode1"));
}
};
自定义蓝图节点
这里使用的是继承UK2Node实现的! 在MyEditorTools的模块中添加节点类,并继承UK2Node
#pragma once
#include "K2Node.h"
#include "CustomNode.generated.h"
UCLASS()
class UCustomNode : public UK2Node
{
public:
GENERATED_BODY()
virtual FText GetTooltipText() const override {return FText::FromString(TEXT("This is a test case"));};
virtual FText GetNodeTitle(ENodeTitleType::Type TitleType) const override {returnFText::FromString(TEXT("Custom Node"));};
virtual FText GetMenuCategory() const override{return FText::FromString(TEXT("Custom|CustomNode"));};
virtual void GetMenuActions(FBlueprintActionDatabaseRegistrar& ActionRegistrar) const override;
virtual void ExpandNode(FKismetCompilerContext& CompilerContext, UEdGraph* SourceGraph) override;
virtual void AllocateDefaultPins() override;
UEdGraphPin* GetThenPin() const;
};
cpp
#include "CustomNode.h"
#include "BlueprintActionDatabaseRegistrar.h"
#include "BlueprintNodeSpawner.h"
#include "EdGraphSchema_K2.h"
#include "K2Node_CallFunction.h"
#include "KismetCompiler.h"
void UCustomNode::GetMenuActions(FBlueprintActionDatabaseRegistrar& ActionRegistrar) const
{
Super::GetMenuActions(ActionRegistrar);
auto Classkey = GetClass();
if (ActionRegistrar.IsOpenForRegistration(Classkey))
{
auto nodeSpawner = UBlueprintNodeSpawner::Create(Classkey);
check(nodeSpawner!= nullptr);
ActionRegistrar.AddBlueprintAction(nodeSpawner);
}
}
void UCustomNode::ExpandNode(FKismetCompilerContext& CompilerContext, UEdGraph* SourceGraph)
{
Super::ExpandNode(CompilerContext, SourceGraph);
}
void UCustomNode::AllocateDefaultPins()
{
Super::AllocateDefaultPins();
}
UEdGraphPin* UCustomNode::GetThenPin() const
{
UEdGraphPin* Pin = FindPin(UEdGraphSchema_K2::PN_Then);
check(Pin == nullptr || Pin->Direction == EGPD_Output); // If pin exists, it must be input
return Pin;
}
这个时候编译完成后,我们就能在蓝图里看到新加的节点了!
GetTooltipText方法是鼠标浮在节点上的提示!
GetNodeTitle是节点的名称!
GetMenuCategory是节点的归类目录
GetMenuActions是将节点注册到蓝图的右键菜单中!
注意:如果是plugin或者是独立的module的话,想要生效,需要重新reload或者在ue中compiler!
蓝图节点在构建展示的时候,会默认调用AllocateDefaultPins,所以我们如果想要想其他默认节点那样能接入到流程中,需要在AllocateDefaultPins中添加一些代码
void UCustomNode::AllocateDefaultPins()
{
CreatePin(EGPD_Input, UEdGraphSchema_K2::PC_Exec, UEdGraphSchema_K2::PN_Execute);
CreatePin(EGPD_Output, UEdGraphSchema_K2::PC_Exec, UEdGraphSchema_K2::PN_Then);
Super::AllocateDefaultPins();
}
使用CreatePin去创建流入和流出的pin,需要注意的是,这里的第三个参数是name,但是有不全是!最好是先默认UEdGraphSchema_K2::PN_Execute和UEdGraphSchema_K2::PN_Then;
你可以试试换成中文;eg: TEXT("输入"),TEXT("输出");看看能不能调用和debug!!
试试连接起来编译看看
原因是该节点没有执行的函数!需要在ExpandNode中绑定!
void UCustomNode::ExpandNode(FKismetCompilerContext& CompilerContext, UEdGraph* SourceGraph)
{
Super::ExpandNode(CompilerContext, SourceGraph);
// 获取流入的pin
auto execPin = GetExecPin();
// 获取流出的pin
auto thenPin = GetThenPin();
if (execPin && thenPin)
{
// 获取要执行的方法名,需要注意,一定要有UFUNCTION,
auto functionName = GET_FUNCTION_NAME_CHECKED(UCustomRunningNode, TestBlueprintNode2);
// 构建要执行的方法节点!
auto callFunction = CompilerContext.SpawnIntermediateNode<UK2Node_CallFunction>(this, SourceGraph);
// 设置并绑定执行的方法体
callFunction->FunctionReference.SetExternalMember(functionName, UCustomRunningNode::StaticClass());
callFunction->AllocateDefaultPins();
// 流程转移!
CompilerContext.MovePinLinksToIntermediate(*execPin, *(callFunction->GetExecPin()));
CompilerContext.MovePinLinksToIntermediate(*thenPin, *(callFunction->GetThenPin()));
}
// 断开所有的link
BreakAllNodeLinks();
}
这里的UCustomRunningNode是在项目运行时的module中的
UCLASS()
class UNREALGAMEDEMO_API UCustomRunningNode : public UObject
{
public:
GENERATED_BODY()
UFUNCTION(BlueprintCallable)
static void TestBlueprintNode2()
{
UE_LOG(LogUnrealGameDemo, Display, TEXT(&#34;UCustomRunningNode::TestBlueprintNode2&#34;));
}
};
执行编译和reload后,一切正常了!debug和执行都没有问题了!
补充
[*]PinDefaultValueChanged
当蓝图的节点的内容发生改变的时候,此函数是回调!
[*]CreatePin
该节点支持很多种类型的内容
Bool,
Byte,
Class,
SoftClass,
Int,
Int64,
Float,
Name,
Delegate,
Object,
Interface,
SoftObject,
String,
Text,
Struct,
Enumeg : CreatePin(EGPD_Input, TEXT(&#34;Struct&#34;), TEXT(&#34;AName&#34;));
页:
[1]