UE4学习笔记:在项目和插件里创建新C++模块的方法

本随笔介绍如何在UE4项目和插件里创建新的C++模块的方法。因为官方引擎并没有提供直接创建模块的方法[1],所以通过本随笔记录一下通用的创建方式。

随笔作者还在学习阶段,对UE4引擎的使用和理解还不是非常透彻,难免会在随笔内容里出现技术上或书写上的问题,如果出现了类似的问题欢迎在评论区或者私信讨论。

前置工作

我已经提前新建了一个名为“AddModuleTest”的UE4C++项目,并且在其中新建了一个名为“ModulePlugin”的C++插件,而在本随笔的最后我们会创建一个新的名为“NewModule”的模块。因为模块是在UE4C++代码里面才会有的概念,所以无论是要在项目或者插件里添加模块,都需要是C++类型而不能是蓝图类型。在项目里添加模块并不需要其所有插件都为C++插件,甚至都不需要插件,但是如果要在插件里面添加模块的话就一定需要项目是C++类型,因为我们需要用到项目的Visual Studio工程去构建新建的模块。本随笔的大部分篇幅我会以新建插件模块的方法去描述,因为项目模块的创建方法和插件模块的创建方法一致,只是在部分设置上会有所区别,区别的内容我会在随笔最后介绍。

新建模块文件夹

插件(Plugin)或项目都是由模块(Module)组成,因此也可以说每个插件或项目都会至少包含一个模块,在文件资源管理器展示的目录结构里,每个模块需要用到的所有文件都会被包含到被命名为模块名字的文件夹内,而这些文件夹都会被放到源码文件夹里,该文件夹被命名为“Source”。项目有自己的唯一一个源码文件夹,插件同样也有唯一的源码文件夹:
插件的源码文件夹
新建的模块文件夹也需要放置到源码文件里面,在本随笔中我新建了一个名为“NewModule”的模块文件夹在插件源码文件夹里:
在插件源码文件夹里的新模块文件夹

可从上图里面看到,插件源码文件夹里面已经存在了一个模块文件夹“ModulePlugin”,这些模块文件夹是默认由引擎创建的,且名字与插件名称一致。新建的模块名称没有任何硬性的规定

新建模块文件

不论是在项目里新建模块还是在插件里新建模块,模块所需要的的基础文件一共有三个,一个是模块定义头文件(.h),一个是模块定义源文件(.cpp),这两个文件统称为模块定义文件,还有一个模块构建文件(.Build.cs)

新建模块定义头文件

模块定义头文件是模块定义所需要用到的头文件,该头文件的命名格式为“<ModuleName>.h”,其中尖括号的文字表示可以被任意替换,一般来说是替换为模块的名字。需要注意的是尖括号本身并不是文字的内容,因此也需要被替换掉。在本随笔中我新建了一个名为“NewModule.h”的模块定义头文件:
新建的模块定义头文件
该头文件的作用主要是用来声明我们要定义的模块在C++代码里的,模块定义头文件的内容格式如下:

// Copyright message here.

#pragma once

#include "Modules/ModuleManager.h"

class <ModuleClassName> : public IModuleInterface
{
public:
	virtual void StartupModule();
	virtual void ShutdownModule();
};

其中尖括号包含的文字<ModuleClassName>是可以任意替换的内容,一般是替换为模块的类名,且尖括号也需要被替换掉。这里需要注意的是,实际的文字是模块的类名而不是模块的名称。本随笔中我们要新建一个名称为“NewModule”的模块,按照UE4C++代码规范编写的话那么这个类名就是FNewModule,也就是说我们模块定义头文件的内容应该是下面的格式:

// Copyright message here.

#pragma once

#include "Modules/ModuleManager.h"

class FNewModule : public IModuleInterface
{
public:
	virtual void StartupModule();
	virtual void ShutdownModule();
};

新建模块定义源文件

模块定义源文件是定义模块定义头文件里声明了的模块类所需要用到的文件,该源文件的命名格式为“<ModuleName>.cpp”,在本随笔中我们新建的模块定义源文件的名称应为“NewModule.cpp”:
新建的模块定义源文件
模块定义源文件的内容格式如下:

// Copyright message here.

#pragma once

#include "<ModuleName>.h"

void <ModuleClassName>::StartupModule()
{
}

void <ModuleClassName>::ShutdownModule()
{
}

IMPLEMENT_MODULE(<ModuleClassName>, <ModuleName>)

其中尖括号包含的文字<ModuleName>即为模块名字,这里通俗来讲其实就是需要包含模块定义头文件。额外的尖括号文字<ModuleClassName>即为模块的类名,最后一行的代码是一个宏,该宏实现了将模块类暴露给项目使用的功能,因此会接收两个参数,一个是要暴露的模块类的名字,一个是暴露后模块的名字。在本随笔中我们的模块定义源文件内容就会是如下格式:

// Copyright message here.

#pragma once

#include "NewModule.h"

void FNewModule::StartupModule()
{
}

void FNewModule::ShutdownModule()
{
}

IMPLEMENT_MODULE(FNewModule, NewModule)

新建模块构建文件

模块构建文件是一个特殊的模块文件,该文件由C#编写,其作用是控制该模块如何与其他模块进行交互,模块构建文件的命名格式为“<ModuleName>.Build.cs”,在本随笔中我们新建的模块构建文件名称就为“NewModule.Build.cs”:
新建的模块构建文件
模块构建文件的内容格式如下:

// Copyright message here

using UnrealBuildTool;

public class <ModuleName> : ModuleRules
{
	public <ModuleName>(ReadOnlyTargetRules Target) : base(Target)
	{
		PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs;

		PublicDependencyModuleNames.AddRange(new string[] { "Core" });

		PrivateDependencyModuleNames.AddRange(new string[] { "CoreUObject", "Engine", "Slate", "SlateCore" });
	}
}

模块构建文件看起来很长,实际上需要改写的地方就只有两处,只需要将尖括号包含的文字<ModuleName>改写为实际的模块名称即可,在本随笔中我们的模块构建文件的内容格式如下:

// Copyright message here

using UnrealBuildTool;

public class NewModule : ModuleRules
{
	public NewModule(ReadOnlyTargetRules Target) : base(Target)
	{
		PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs;

		PublicDependencyModuleNames.AddRange(new string[] { "Core" });

		PrivateDependencyModuleNames.AddRange(new string[] { "CoreUObject", "Engine", "Slate", "SlateCore" });
	}
}

添加新模块信息

插件描述文件(Plugin Descriptor)里添加新的模块描述符
添加模块描述符
其中被选中的部分即为我们需要手动添加的部分。

构建新添加的模块

打开项目的Visual Studio工程,重新构建我们的项目(“生成(Build)”或者“重新生成(Rebuild)”都可以),构建完成之后即可在项目里面找到我们新创建的模块:
在添加新C++类的时候可以选择要被添加的模块

添加项目模块与添加插件模块的区别

  • 新建模块文件夹小节,新创建的模块文件夹要放到项目源码文件夹里面而不是插件源码文件夹
  • 添加新模块信息小节,添加新的模块描述符应该在项目描述文件里而不是插件描述文件里。
  • 需要额外在项目目标文件里添加新建的模块名称。项目目标文件被放置在项目源码文件夹里,是以“.Target.cs”结尾的文件,默认情况下项目会存在两个目标文件:“<ProjectName>.Target.cs”和“<ProjectName>Editor.Target.cs”,这两个目标文件分别指定了在Game模式和Editor模式下需要编译的模块名称,根据需要可以添加新的目标文件,除了Editor类型,还可以是Client类型和Server类型等等。关于项目目标文件的详细信息请查阅官方文档。在我们的例子里,我们只需要在Editor模式下编译该模块即可,也就是在“<ProjectName>Editor.Target.cs”目标文件里添加我们的模块即可:
    在项目目标文件里添加新建的模块名称
  • 完成上述的操作之后执行构建新添加的模块小节里的操作,即可实现在项目里添加模块。

利用插件来生成新模块

我个人在开发过程中发现生成新模块的需求比较大,UE4也并没有提供一个很便捷的方式来生成模块,因此我自己编写了一个可以自动生成模块的UE4的插件:Source Module Generator,该链接为Github的仓库链接,可以直接到Release界面里下载已经编译好的版本来使用。使用过程中如果出现Bug也欢迎通过博客园私信或在Github上发Issue的方式来告知我,我会尽快修复。需要注意的是二进制插件版本目前只支持Windows 64位操作系下的UE4.27版本使用。


  1. 编写本随笔时官方引擎最新版本为4.27。 ↩︎

posted @ 2021-09-10 17:14  U_N_Owen  阅读(3991)  评论(0编辑  收藏  举报