关于 unreal-blueprint-codegen
unreal-blueprint-codegen 是面向 Unreal Engine 5.4–5.7 编辑器模块开发者的技能,用 C++ 程序化生成 Blueprint、Widget Blueprint 等 .uasset。它提供节点连线、编译、保存流程及版本注意事项,适用于可重复生成资产的场景。
主要功能
- 01用 C++ 生成 Blueprint 资产
- 02构建函数图和事件图
- 03生成 Widget Blueprint 层级与动画
- 04编译并保存资产包
- 05提供双阶段编译指导
- 06整理引擎版本注意事项
适用场景
- 01批量生成可重复使用的示例资产
- 02程序化创建 Blueprint 变量和节点
- 03从 C++ 构建 Widget Blueprint 与动画
- 04排查节点引脚或编译问题
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ maystudios/ claude-skills --skill unreal-blueprint-codegen安装后在 Claude Code 中输入/unreal-blueprint-codegen确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
assets/experiment-module-template/uplugin-snippet.jsonassets/experiment-module-template/Source/MyExperimentEditor/MyExperimentEditor.Build.csassets/experiment-module-template/Source/MyExperimentEditor/Private/MyExperimentEditorModule.cppMyExperimentLibrary.cppassets/experiment-module-template/Source/MyExperimentEditor/Public/MyExperimentEditorModule.hMyExperimentLibrary.hreferences/caveats.mdk2node-cookbook.mdtwo-pass-compile.mdwidget-blueprint-cookbook.md详细介绍
Unreal Engine Blueprint 代码生成(UE 5.4–5.7)
在编辑器模块中从 C++ 生成完整的 .uasset 文件(Blueprint、Widget Blueprint、领域资源)。已针对 UE 5.7 验证。大多数模式也适用于 UE 5.4 及更高版本。
适用场景
用户希望以编程方式创作资源内容——变量、函数图表、事件图表连线、Widget 层级结构、UMG 动画、自定义资源图表——而不是在编辑器中逐项点击。典型用例:生成 Marketplace 示例内容(快速入门、操作指南、演示对话),使其能够以可复现的方式重新生成,而不是手动精简二进制 .uasset 文件。
如果用户只想在运行时实例化 Widget(游戏运行时调用 CreateWidget / WidgetTree->ConstructWidget),那么这项技能有点大材小用——那只是常规 UMG 操作。
硬性前提
- C++ 编辑器模块,
Type=Editor(或UncookedOnly)。Python 无法创作事件图表——UEdGraph/UK2Node_*不对外开放。如果需要 Python 入口,请在 C++ 中设置UBlueprintFunctionLibrary,并从 Python 调用其 UFUNCTION。 - 模块至少需要依赖:
UnrealEd、BlueprintGraph、Kismet、KismetCompiler、AssetTools、AssetRegistry。对于 Widget Blueprint,还需添加UMG、UMGEditor、MovieScene、MovieSceneTracks。可参阅 assets/experiment-module-template/ 中可正常工作的.Build.cs。 - IWYU:显式包含每个引擎头文件。在自己的头文件中前置声明
UPackage/UObject等;仅在.cpp中引入完整头文件。
30 秒快速理解
Asset = UPackage + UObject (e.g. UBlueprint / UWidgetBlueprint / UMyAsset)
|
+-- source UEdGraph (editor-only, what designers see)
| +-- UK2Node_* / UEdGraphNode_* (the boxes)
| +-- UEdGraphPin (the wires)
|
+-- generated UClass <- produced by CompileBlueprint
+-- FProperty / UFunction (what code uses at runtime)
在图表上生成编辑器节点,连接它们的引脚,然后调用 CompileBlueprint 生成类。保存包。
决策树
| 目标 | 阅读 |
|---|---|
| 向常规 Blueprint 添加变量、函数、自定义事件、数学节点 | references/k2node-cookbook.md |
| 构建包含 Widget 层级结构的 Widget Blueprint | references/widget-blueprint-cookbook.md |
| 从 C++ 添加 UMG 动画(UWidgetAnimation + MovieScene 轨道/关键帧) | references/widget-blueprint-cookbook.md |
编译器提示“找不到函数”、FindPinChecked 断言失败,或节点没有引脚 | references/two-pass-compile.md — 调试前请先阅读 |
| 需要一个可供起步的模块骨架 | assets/experiment-module-template/ |
| 遇到奇怪的引擎 API 特性或特定版本问题 | references/caveats.md |
标准工作流
对于每个生成器函数:
- 创建/加载包:调用
CreatePackage(*FullPath),然后调用Package->FullyLoad()。 - 创建资源:使用
FKismetEditorUtilities::CreateBlueprint(...)(同时适用于UBlueprint和UWidgetBlueprint——传入正确的 Blueprint 类 + GeneratedClass)。 - 构建内容——变量、函数图表、Widget 树、动画。
- 连接事件图表/调用用户函数——仅当连线引用了步骤 3 中创建的内容时,才在中间编译后执行(参阅 two-pass-compile.md)。
MarkBlueprintAsStructurallyModified+CompileBlueprint——最后调用一次(或分两阶段调用两次)。- 保存:调用
FAssetRegistryModule::AssetCreated(Asset)+Package->MarkPackageDirty()+UPackage::SavePackage(...)。
骨架:
#include "Engine/Blueprint.h"
#include "Kismet2/BlueprintEditorUtils.h"
#include "Kismet2/KismetEditorUtilities.h"
#include "AssetRegistry/AssetRegistryModule.h"
#include "UObject/SavePackage.h"
UBlueprint* CreateBP(const FString& PackagePath, const FString& AssetName, UClass* ParentClass)
{
const FString FullPath = PackagePath / AssetName;
UPackage* Package = CreatePackage(*FullPath);
Package->FullyLoad();
UBlueprint* BP = FKismetEditorUtilities::CreateBlueprint(
ParentClass, // e.g. AActor::StaticClass() or UUserWidget::StaticClass()
Package,
FName(*AssetName),
BPTYPE_Normal,
UBlueprint::StaticClass(), // or UWidgetBlueprint::StaticClass()
UBlueprintGeneratedClass::StaticClass(), // or UWidgetBlueprintGeneratedClass::StaticClass()
FName("MyGenerator")); // calling-context tag; any FName
// ... build content here ...
FBlueprintEditorUtils::MarkBlueprintAsStructurallyModified(BP);
FKismetEditorUtilities::CompileBlueprint(BP);
FAssetRegistryModule::AssetCreated(BP);
Package->MarkPackageDirty();
const FString Filename = FPackageName::LongPackageNameToFilename(
Package->GetName(), FPackageName::GetAssetPackageExtension());
FSavePackageArgs Args;
Args.TopLevelFlags = RF_Public | RF_Standalone;
UPackage::SavePackage(Package, BP, *Filename, Args);
return BP;
}
关键规则(即使跳过操作指南也请阅读)
1. 在 UK2Node_CallFunction 上调用 AllocateDefaultPins 之前,先设置 SetExternalMember
UK2Node_CallFunction* Node = NewObject<UK2Node_CallFunction>(Graph);
Node->FunctionReference.SetExternalMember(
GET_FUNCTION_NAME_CHECKED(UKismetSystemLibrary, PrintString),
UKismetSystemLibrary::StaticClass());
Node->AllocateDefaultPins(); // AFTER. Reverse and the node spawns pinless.
UK2Node_VariableSet/Get 也遵循相同规则:先设置变量引用,再调用 AllocateDefaultPins。
2. MarkBlueprintAsStructurallyModified 与 Modified
- StructurallyModified:添加或移除任何节点、添加或移除任何变量、引脚拓扑发生任何变化。强制重新生成类布局。
- Modified:仅调整现有节点或变量的属性(例如更改默认值)。
对于代码生成,几乎总是使用 MarkBlueprintAsStructurallyModified。
3. 函数调用必须接入执行链,否则会被剔除
非纯函数(带有执行引脚)必须接入执行链。如果连接了它们的数据输出,却没有连接执行引脚,BP 编译器就会剔除该调用,数据引脚将读取默认值。表现为警告 "由于未连接其 Exec 引脚,X 已被剔除"。
// WRONG — Compute is non-pure, exec not wired, gets pruned:
EvtThen->MakeLinkTo(SetCounter->GetExecPin());
ComputeRet->MakeLinkTo(CounterValPin); // reads default, not actual return
// RIGHT — Compute in the chain:
EvtThen->MakeLinkTo(CallCompute->GetExecPin());
CallCompute->GetThenPin()->MakeLinkTo(SetCounter->GetExecPin());
ComputeRet->MakeLinkTo(CounterValPin);
4. 避开 (0,0)——自动生成的默认事件位于此处
基于 AActor 的 BP 和 Widget Blueprint 都会在 (0, 0) 自动生成占位事件(BeginPlay、Tick、ActorBeginOverlap、PreConstruct、Construct)。请将节点放在远处,例如 Y=-300、X=-400。否则,用户打开资源时会看到一团乱麻。
5. 节点引用新建内容时,分两轮编译
如果创建函数 Compute,然后在同一轮中连线引用它的 CallCompute,那么 CallCompute 上的 AllocateDefaultPins 会在 Compute 反映到生成的类之前运行——InValue/ReturnValue 的引脚不会存在,导致 FindPinChecked 触发断言。解决方法:构建函数后先编译,再连接调用。通过 UK2Node_VariableGet 引用 UMG 动画时也一样。请参阅 references/two-pass-compile.md。
UE 5.7 常见问题(完整列表见 caveats.md)
PlayAnimationByName在 5.7 的UUserWidget上不存在。 只有PlayAnimation(UWidgetAnimation*, ...)。请通过UK2Node_VariableGet获取动画,而不是使用字符串。- 动画
FName必须与显示标签相同。UUserWidget::GetAnimationByName会匹配GetFName()。两者都要设置:NewObject<UWidgetAnimation>(WBP, FName("SlideIn"), ...),以及Anim->SetDisplayLabel(TEXT("SlideIn"))。 Outer层级至关重要。UWidgetAnimation的外层对象必须是 WBP。UMovieScene的外层对象必须是动画。外层对象错误 → 动画不会出现在编辑器的 Animations 面板中。- 生成的资源引用的所有标签都必须使用
UE_DEFINE_GAMEPLAY_TAG_STATIC。 在生成器函数中运行时调用UGameplayTagsManager::AddNativeGameplayTag为时已晚——编辑器 UI 的标签树已经构建完成。请在模块加载时注册。 - Python 无法访问
UEdGraph/UK2Node_*。 编写事件图的唯一方式是使用 C++。如果需要通过 Python 调用,请将生成器作为BlueprintCallableUFUNCTION 暴露在UBlueprintFunctionLibrary上。 FBlueprintEditorUtils::AddFunctionGraph默认不会生成 Result 节点。 只有 Entry。如果函数有返回值,请使用FGraphNodeCreator<UK2Node_FunctionResult>手动创建一个。
FEdGraphPinType 速查表
FEdGraphPinType T;
T.PinCategory = UEdGraphSchema_K2::PC_Boolean; // bool
T.PinCategory = UEdGraphSchema_K2::PC_Int; // int32
T.PinCategory = UEdGraphSchema_K2::PC_Real;
T.PinSubCategory = UEdGraphSchema_K2::PC_Float; // float
T.PinSubCategory = UEdGraphSchema_K2::PC_Double; // double
T.PinCategory = UEdGraphSchema_K2::PC_String; // FString
T.PinCategory = UEdGraphSchema_K2::PC_Name; // FName
T.PinCategory = UEdGraphSchema_K2::PC_Text; // FText
T.PinCategory = UEdGraphSchema_K2::PC_Object; // object ref
T.PinSubCategoryObject = AActor::StaticClass(); // (with target class)
T.ContainerType = EPinContainerType::Array; // wrap as TArray<>
T.ContainerType = EPinContainerType::Set; // TSet<>
T.ContainerType = EPinContainerType::Map; // TMap<> (PinValueType for value)
与以下代码搭配使用:FBlueprintEditorUtils::AddMemberVariable(BP, FName("MyVar"), T, FString(TEXT("DefaultValueAsString")));
工作流检查清单
使用此技能实现生成器时:
- 确认编辑器模块及其所需依赖项均已存在(模板见 assets/experiment-module-template/)。
- 阅读 references/k2node-cookbook.md,了解适用于相应资源类型的模式。
- 对于 Widget 蓝图,还要阅读 references/widget-blueprint-cookbook.md。
- 如果连线涉及同一函数中创建的内容,请规划两遍编译结构(references/two-pass-compile.md)。
- 在认定新行为是错误之前,先查阅 references/caveats.md,了解已知陷阱。
- 测试时,先构建编辑器目标,再打开编辑器、调用 UFUNCTION(通常通过输出日志中的 Python),并目视检查资源。
- 反复迭代:如果节点看起来不对(红色错误边框、缺少引脚、“X 个已修剪”警告、数据应流经之处却显示默认值),通常是以下原因之一:缺少执行线、分配顺序错误、缺少两遍编译,或引脚名称错误。
此技能不涵盖的内容
- 生成资源的烹饪 / 打包——它们是常规
.uasset文件,和其他资源一样打包发布。 - 编辑器实用工具控件 / Blutilities——你可以从中调用生成器 UFUNCTION,但设计 EUW 属于单独的 UMG 工作。
- 运行时 UMG——游戏代码中的
CreateWidget、AddToViewport、动画PlayAnimation调用。这不属于代码生成。 - 自定义 UEdGraph 模式——如果要生成到特定领域的图表(对话、任务、能力树)中,请使用插件自己的编译器入口点。静态编译器类通常不会导出,因此如果链接失败,请调用图表的更新方法(例如
UMyGraph::UpdateAsset()),而不是静态编译器。