fatal error lnk1561: 必须定义入口点_浅析创建自定义资源

本文详细介绍了在Unreal Engine 4.22.0中创建自定义Editor Widget资源的过程,包括AssetTypeActions、资源类、Factory以及注册资源分组的步骤。通过分析源码,解释了如何解决在开发中遇到的显示和运行时崩溃问题,为自定义蓝图资源的创建提供了清晰的指导。
摘要由CSDN通过智能技术生成

引擎版本 4.22.0

前言

在实际的开发中我们可能需要创建自定义资源,很遗憾的是官方文档中并没有提供相关教程。本文将以引擎的Editor Widget创建为例配合源码介绍如何创建自定义资源。

注意源码图片看不清楚的看这里:http://note.youdao.com/noteshare?id=54fed93922a7fbeed459519437e30abe

Editor Widget简介

a0660e4ae1f043878d9ea11f1a52aa8a.png

先上官方文档关于这方面的介绍:

https://docs.unrealengine.com/zh-CN/Engine/UMG/UserGuide/EditorUtilityWidgets/index.html

简单来讲Editor Widget就是在编辑器环境下使用的Widget,只不过该Widget可以显示在编辑器窗口中罢了。该资源为蓝图资源,类型为UEditorUtilityWidgetBlueprint,该蓝图资源的ParentClassUEditorUtilityWidget

437a0b9d945f4ba36aa0bed11222695c.png

我们常用的UserWidget同样也是蓝图资源,类型为UWidgetBlueprintParentClassUUserWidget

看一下类结构示意图:

83e1b631a8b3b76105df193b213d23f5.png

可以看出EditorWidget是从UserWidget扩展而来,因为有自己的蓝图类,所以是独立的资源。

自定义资源创建相关类

  • AssetTypeActions

AssetTypeActions是用来创建资源的入口,常见的是我们在内容浏览器中空白出右键出现的一系列将要创建的资源列表:

0a258a1a48c1da6603356ee2287e9008.png

以及右键一个资源出现与该资源相关的一些操作:

dc49ae7ef2bbeb31aa891fc7db67eda6.png

该类中还会指定打开该资源的编辑器,例如我们的EditorWidget双击后打开的编辑器就是专门设计的编辑器:

8c20362ff97501ac6c44af6a8c5f1d5b.png

看一下EditorWidget关于该类的源码:

02688141fe33bd4096494bc881533cc8.png

接下来挑几个重要的也是必须重写的方法介绍下:

1. GetName是用来显示该资源的类型名,由于被指定为EditorWidget

373ca78358b3293b103b8e00ebce22d5.png

所以当我们将鼠标悬浮在该类型资源上时Tip中会显示对于的类型名:

4c83f2992e99af5764cb6075964a9754.png

2. GetTypeColor是该资源的图标颜色:

f9f8b31202d31e5752949051db17e7bb.png

3. GetSupportedClass指定了资源对应的类:

fdbae134d45e54d0951bd7675224ced6.png

4. HasActions指定该资源是否有相应的右键操作选项:

e55d8d288b3487e6253aad5acd9721e8.png

5. GetActions定义了右键操作选项:

129c3554908711d069bf6cb547d79b73.png

从图中可以看出EditorWidget中定义了一个右键操作选项:Run Editor Utility Widget,也就是在窗口中预览界面:

a84bb5a1291da4502d64025563ec3690.png

6. OpenAssetEditor中指定了打开资源的编辑器,具体查看源码

7. GetCategories中指定了创建资源的选项在右键菜单中的分组:

cb584987d83ee78b7612bc8541430c37.png
  • 资源类

EditorWidget的资源类为UEditorUtilityWidgetBlueprint:

d33199cad9125286decbba7062c36183.png

同样地介绍下主要的方法:

1. GetReparentingRules方法指定了更改蓝图资源ParentClass的规则:

d045c4ad3dc8ef7d51821e935f26c040.png

从图中可见代码中定死了只能使用UEditorUtilityWidget及其子类:

00061d5c4fee7542a18ca750e5092562.png
  • Factory

每个自定义资源还需要有一个创建该资源的工厂:

a7375949fb403e6015ff9ef7a12891c1.png

构造函数中需要进行一些设置:

91e2aeb710e64ea54b83f98456f06cf8.png

SupportClass就是资源类,ParentClass就是蓝图父类。

同样我们需要重写FactoryCreateNew方法,里面主要创建蓝图资源并指定其父类,具体可参考源码。FactoryCreateNew方法的调用时机在资源命名完毕并提交的时候。

注册AssetCategory

自定义资源在右键创建入口需要有新的分组则需要注册,例如EditorWidget就在BlutilityModule模块启动函数中注册了EditorUtilities组:

9f9fbc6cea6d7b3080f9a64795c82660.png

注意不要忘记了在AssetTypeActionsGetCategories方法中指定自定义分组:

1e207e28b096f45d990b34636a2d840c.png

源码中是将注册的资源分组存在模块的EditorUtilityCategory变量中,AssetTypeActions类中就通过模块获得资源分组。

需要注意的是有一种更为方便的方法就是通过AssetToolFindAdvancedAssetCategory方法获取:

571b0b8ae7db1698e37c1074b54c1844.png

注册AssetTypeActions

为保证AssetTypeActions生效还得将其注册,源码是在BlutilityModule模块启动时注册的:

747d468c78087d39a067b6f411926d4f.png

注销AssetTypeActions

BlutilityModule关闭时会注销AssetTypeActions:

744efe21e8d798b9f1e9bd30ee686401.png

实践

笔者需要创建一个默认父类为MyUserWidget的Widget资源,所以就仿照Editor Widget实现了,不妨看下效果:

1ce0969f92b3da6227d6a1e0474d6f05.png

1334a24398ba95d5aefe52c4112724f3.png

652a120e254eb1ef8e5886e01fca6520.png

a1aa93af5374b2eb8a17a45b0ba8d066.png

在实际操作中遇到两个问题:

1.在Widget编辑器中嵌套使用UserWidget不显示的问题

发现是WidgetTree->RootWidget为空,需要在模块启动时对自定义蓝图资源注册器。

FKismetCompilerContext::RegisterCompilerForBP(UMyWidgetBlueprint::StaticClass(), &UWidgetBlueprint::GetCompilerForWidgetBP);

2.在编辑器中以Mobile Preview模式启动崩溃问题

崩溃日志:

LogStreaming: Error: Couldn't find file for package /Script/FrameworkEditor requested by async loading code. NameToLoad:/Script/FrameworkEditor
LogLinker: Warning: Unable to load InforItemUI with outer Package /Game/UserInterface/Widget/GMUI/GMLogin/InforItemUI because its class does not MakeSureDirExists

Fatal error: [File:D:Build++UE4SyncEngineSourceRuntimeCoreUObjectPrivateTemplatesCasts.cpp] [Line: 10]
Error: Cast of LinkerPlaceholderExportObject /Game/UserInterface/Widget/GMUI/GMLogin/InforItemUI.PLACEHOLDER-INST_of_PLACEHOLDER-CLASS__MyWidgetBlueprint_1 to Blueprint failed.

原因是由于MyWidgetBlueprint定义在FrameworkEditor模块中,而界面InforItemUI的蓝图资源为自定义的MyWidgetBlueprint。当以Mobile Preview模式启动时FrameworkEditor模块未加载导致未能正确找到MyWidgetBlueprint,从而在BlueprintGeneratedClass::GetAuthoritativeClass()中将ClassGeneratedBy转化为UBlueprint失败从而导致崩溃。解决方法为在运行时模块启动时手动载FrameworkEditor模块。

void FFrameworkModule::StartupModule()
{
    #if WITH_EDITOR
    FModuleManager::Get().LoadModule(TEXT("FrameworkEditor"));
    #endif
}

之前纳闷的地方在于我写的MyWidgetBlueprint是继承引擎的UWidgetBlueprint的,而UWidgetBlueprint是属于UMGEditor模块的。它之所以没事是因为FEngineLoop::LoadStartupCoreModules()中手动加载了UMG模块,而当UMG模块启动又加载了UMGEditor模块。

本文介绍的是蓝图类资源的创建流程,了解了流程就可以很方便地自定义非蓝图类的资源,这里就不再详细介绍了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值