UE 在C++中生成一个基于蓝图的Actor

本文介绍了如何在Unreal Engine 4中通过C++代码动态创建已有的蓝图类Actor,包括类声明、使用FClassFinder查找蓝图、SpawnActor函数的用法,并展示了关键步骤和参数含义。

简介

        在UE4游戏场景中看到的所有对象皆是Actor,而Actor复杂的功能是由许多不同的Component共同实现的。Actor是Object的基类,它是一个可以放置或生成在世界中的对象。

        当我们想要在场景中创建一个物体时,先要创建一个继承于Actor的C++类,再基于该C++类创建蓝图类,然后只要把这个蓝图拖进场景中就可以了。那我们如果想要使用代码在场景中批量生成已经创建好的蓝图,也就是动态创建该怎么办呢?


代码实现

        首先在头文件中声明要创建的蓝图类的对象,使用 TSubclassOf 限定变量的类型只能是要创建的蓝图类或者该蓝图类的子类:

TSubclassOf<YourClass> BlueprintVar;        // YourClass是蓝图使用的基类

        然后需要在构造函数中给变量赋值,使用 FClassFinder 找到该蓝图类,要使用 FClassFinder 函数需要包含头文件 "UObject/ConstructorHelpers.h":

// TEXT里面是要创建的蓝图的路径
static ConstructorHelpers::FClassFinder<YourClass> UBlueprint(TEXT("/Game/Blueprints/BlueprintName"));
BlueprintVar = UBlueprint.Class;

        最后使用 SpawnActor() 在场景中生成蓝图的对象,这段代码不可以放在构造函数中,可以把它放在 BeginPlay() 中,或者写在另外的函数中,在想要生成该蓝图对象的时候调用:

FActorSpawnParameters Params;
Params.Owner = this;
GetWorld()->SpawnActor<YourClass>(BlueprintVar, GetActorLocation(), FRotator::ZeroRotator, Params);

        这里说一下 SpawnActor 的每个参数的意思,第一个参数是前面我们声明并赋值的蓝图类的对象,第二个参数是生成的蓝图的位置坐标,这里的 GetActorLocation() 是获取当前类的当前位置,第三个参数是生成的蓝图的旋转角度,这里的 FRotator::ZeroRotator 是不旋转,第四个参数是生成的蓝图对象的拥有者是谁,它是一个默认参数,不填的时候默认没有拥有者。这个参数的类型是 FActorSpawnParameters 的结构体类型,这里是指定当前类为生成的蓝图对象的拥有者。

<think>我们正在回答用户的问题:如何在UE5中使用C++生成控件蓝图。 根据引用[3]:UE5插件创建控件蓝图。其中有一个类CreateWBPMain,它提供了创建控件蓝图的方法。 具体来说,CreateWBPMain类中有一个静态函数:CreateWidgetBlueprint,用于创建控件蓝图。 同时,引用[3]还提到了编译蓝图(CompileBlueprint)和保存蓝图(SavePackage)的方法。 另外,引用[4]和引用[5]提供了关于如何引用蓝图类以及如何绑定蓝图控件的方法,但用户的问题是如何生成(创建)控件蓝图,因此我们主要关注引用[3]。 步骤: 1. 包含必要的头文件:在代码中包含CreateWBPMain.h(如果这是你项目中的类)或者使用引擎提供的相关函数。 2. 调用CreateWidgetBlueprint函数来创建控件蓝图。 3. 编译并保存创建的蓝图。 但是请注意,引用[3]中的代码片段是一个自定义类的实现,它可能是某个插件或自定义工具的一部分。因此,在标准的UE5引擎中,我们通常使用其他方式创建蓝图。 实际上,在UE5中,使用C++代码创建蓝图(包括控件蓝图)是一个高级且不常见的操作,通常通过编辑器自动化工具(如编辑器脚本)来完成。但是,我们也可以使用C++通过编辑器API来实现。 下面是一个更通用的方法,基于UE5的编辑器API(注意:需要在Editor模块中运行): 步骤: 1. 创建一个新的蓝图工厂(例如,创建控件蓝图应该使用UWidgetBlueprintFactory)。 2. 使用工厂创建蓝图资源。 3. 设置蓝图的父类(例如UUserWidget)。 4. 编译并保存蓝图。 但是,由于用户要求参考站内引用,而引用[3]给出了一个具体的类,我们将按照引用[3]提供的思路来实现。 然而,引用[3]没有给出CreateWidgetBlueprint的具体实现,我们无法直接使用。因此,我们需要结合UE5的API来实现类似功能。 这里给出一个可能的实现方法(注意:此代码需要在编辑器模块中运行,通常是在插件或编辑器工具中): ```cpp #include "WidgetBlueprint.h" #include "Kismet2/KismetEditorUtilities.h" #include "Kismet2/BlueprintEditorUtils.h" #include "AssetToolsModule.h" #include "ContentBrowserModule.h" UWidgetBlueprint* CreateWidgetBlueprint(FString Name, FString PackagePath, EObjectFlags Flags) { // 创建包 UPackage* Package = CreatePackage(*PackagePath); Package->Flags |= Flags; // 使用工厂创建控件蓝图 UWidgetBlueprintFactory* Factory = NewObject<UWidgetBlueprintFactory>(); Factory->ParentClass = UUserWidget::StaticClass(); UObject* NewAsset = Factory->FactoryCreateNew(UWidgetBlueprint::StaticClass(), Package, *Name, Flags, nullptr, GWarn); if (UWidgetBlueprint* NewWidgetBlueprint = Cast<UWidgetBlueprint>(NewAsset)) { // 编译蓝图 FKismetEditorUtilities::CompileBlueprint(NewWidgetBlueprint); // 标记包为脏 Package->MarkPackageDirty(); // 通知资源浏览器 FContentBrowserModule& ContentBrowserModule = FModuleManager::LoadModuleChecked<FContentBrowserModule>("ContentBrowser"); ContentBrowserModule.Get().NotifyAssetRegistry().AssetCreated(NewWidgetBlueprint); return NewWidgetBlueprint; } return nullptr; } ``` 注意:上述代码需要包含相应的头文件,并且需要在编辑器环境下运行(因为使用了编辑器模块)。 但是,用户可能希望在不使用编辑器模块的情况下运行(例如在运行时生成控件蓝图),这是不可能的,因为创建蓝图资源是一个编辑器操作。 因此,根据用户的需求,我们可以总结: 如果你想在编辑器扩展(如插件)中使用C++创建控件蓝图,可以使用上述方法。如果你希望在运行时动态创建,那么这是不支持的。通常,在运行时,我们会动态生成已经创建好的控件蓝图实例,而不是创建新的蓝图资源。 引用[4]和[5]提供了在运行时如何引用和操作蓝图控件的方法,例如通过软引用加载一个已经存在的控件蓝图类,然后生成其实例。 总结: 1. 在编辑器中创建控件蓝图资源:使用编辑器API(如上代码)。 2. 在运行时动态生成控件蓝图实例:使用软引用加载蓝图类,然后创建实例。 用户的问题是如何“生成”控件蓝图,我们理解为创建新的蓝图资源,所以重点在编辑器API。 由于引用[3]是一个自定义类的实现,我们没有其完整代码,因此我们使用UE5标准API来实现类似功能。 相关步骤已经在上面的代码中给出。 注意:实际使用时,需要处理错误和异常,并且确保路径正确。 如果你是在编辑器插件中,可以调用这个函数来创建控件蓝图。 另外,引用[3]中还有保存包的方法,我们可以补充: ```cpp void SavePackage(UPackage* Package) { FString PackageFileName = FPackageName::LongPackageNameToFilename(Package->GetName(), FPackageName::GetAssetPackageExtension()); FSavePackageArgs SaveArgs; SaveArgs.TopLevelFlags = RF_Standalone; SaveArgs.SaveFlags = SAVE_None; SaveArgs.Error = GWarn; UPackage::SavePackage(Package, nullptr, *PackageFileName, SaveArgs); } ``` 在创建并编译蓝图后,可以调用SavePackage来保存。 因此,完整的创建并保存的流程是: 1. 创建包。 2. 创建控件蓝图资源。 3. 编译蓝图4. 保存包。 请注意,上述操作都是编辑器操作,需要在编辑器模块中运行。 最后,我们根据用户的问题,给出一个UE5中使用C++生成控件蓝图的方法总结。 </think>在Unreal Engine 5中使用C++生成控件蓝图(Widget Blueprint)主要涉及蓝图资源创建和动态加载两个核心流程,以下是具体方法及关键步骤: --- ### 一、创建控件蓝图资源(编辑器环境) 通过编辑器API在开发阶段创建蓝图资源,需在`Editor`模块中进行(**不可在Runtime运行**): ```cpp #include "WidgetBlueprint.h" #include "Kismet2/BlueprintEditorUtils.h" #include "AssetToolsModule.h" // 创建控件蓝图资源 UWidgetBlueprint* CreateWidgetBlueprintAsset(FString AssetName, FString PackagePath) { // 1. 创建资产工厂 UAssetToolsModule& AssetTools = FModuleManager::LoadModuleChecked<FAssetToolsModule>("AssetTools"); UWidgetBlueprintFactory* Factory = NewObject<UWidgetBlueprintFactory>(); Factory->ParentClass = UUserWidget::StaticClass(); // 设置父类为用户控件 // 2. 创建资产 UObject* NewAsset = AssetTools.Get().CreateAsset( AssetName, PackagePath, UWidgetBlueprint::StaticClass(), Factory ); // 3. 编译并保存 if (UWidgetBlueprint* WidgetBP = Cast<UWidgetBlueprint>(NewAsset)) { FKismetEditorUtilities::CompileBlueprint(WidgetBP); // 编译蓝图[^3] UPackage::SavePackage(WidgetBP->GetPackage(), nullptr, RF_Standalone); // 保存资源 return WidgetBP; } return nullptr; } ``` **关键说明**: 1. **需在编辑器模块运行**:此方法仅在开发阶段有效,无法在打包后游戏中使用[^3] 2. **路径规范**:`PackagePath`需为完整路径(如`"/Game/UI/MyWidgetBP"`) 3. **父类指定**:通过`ParentClass`设置控件蓝图C++基类(通常为`UUserWidget`) --- ### 二、运行时动态加载控件蓝图(Gameplay环境) 在游戏运行时通过软引用加载已创建的控件蓝图资源: ```cpp // 软引用加载控件蓝图类 UClass* LoadWidgetBlueprintClass() { // 1. 构造资源路径 (注意添加'_C'后缀) FSoftClassPath WidgetClassPath(TEXT("Blueprint'/Game/UI/MyWidgetBP.MyWidgetBP_C'")); // 2. 异步加载蓝图类 UClass* WidgetClass = WidgetClassPath.TryLoadClass<UUserWidget>(); //[^4] return WidgetClass; } // 实例化控件 void CreateRuntimeWidget() { if (UClass* WidgetClass = LoadWidgetBlueprintClass()) { UUserWidget* MyWidget = CreateWidget<UUserWidget>(GetWorld(), WidgetClass); MyWidget->AddToViewport(); } } ``` **关键说明**: 1. **资源路径格式**:必须使用完整路径且添加`_C`后缀(`蓝图名.蓝图名_C`)[^4] 2. **异步加载**:`TryLoadClass()`自动处理异步加载队列 3. **绑定控件变量**:在C++基类中使用`UPROPERTY(meta=(BindWidget))`绑定蓝图子控件[^5] --- ### 三、动态生成蓝图Actor组件 若需生成附加控件组件的Actor(如3D UI),需结合`TSubclassOf`模板: ```cpp // 在Actor类中声明 UPROPERTY(EditDefaultsOnly, Category="UI") TSubclassOf<UUserWidget> WidgetClass; // 通过编辑器选择蓝图[^2] // 运行时生成 void AMyActor::SpawnWidgetComponent() { if (WidgetClass) { UUserWidget* UIComponent = CreateWidget(GetWorld(), WidgetClass); // 附加到组件... } } ``` **优势**:`TSubclassOf`自动过滤无效类,避免类型转换错误[^2] --- ### 常见问题解决 1. **编译失败**: - 检查父类是否有效(需派生自`UUserWidget`) - 验证蓝图路径是否在项目Content目录内 2. **控件绑定失败**: - C++变量名必须与蓝图控件**完全一致** - 使用`UPROPERTY(meta=(BindWidgetOptional))`允许空绑定[^5] 3. **资源未加载**: - 确认引用路径包含`_C`后缀(如`bp_widget.bp_widget_C`)[^4] - 使用`FStreamableManager`实现异步预加载 > 完整实例参考Unreal Engine官方插件示例:[Editor Scripting Utilities Plugin](https://docs.unrealengine.com/5.0/en-US/editor-scripting-in-unreal-engine/)
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值