UE4 Program 类型工程的限制和解决方法
目前如果你想在 UE4 里创建一个 Program 工程的话,存在两点限制,第一需要将工程源文件都放在 Engine/Source/Programs 目录下,第二是必须使用源码版本的引擎来编译。一般来说也没什么问题,但是有些时候会带来一些问题,比如你的 Program 有着特定的用途只和特定的项目相关,放在引擎目录下稍显不合适,会污染引擎代码结构。怎么样解决这两点限制,构建更加干净的项目?
本文的示例工程地址:MyProject ,测试的引擎版本为:4.24
在引擎目录外创建 Program 工程
首先随便创建一个游戏工程,如果 MyProject,目录结构如下
MyProject
|---MyProject.uproject
|---Config
|---Content
|---Source
|---MyProject.Target.cs
|---MyProjectEditor.Target.cs
|---MyProject
|---MyProject.Build.cs
|---MyProject.cpp
|---MyProject.h
|---MyProjectGameModeBase.cpp
|---MyProjectGameModeBase.h
类似引擎目录结构,在 Source 目录下新建两个子目录:Programs 用来放所有的 Program 工程模块;Runtime 用来放游戏相关的工程模块。然后将原来 Source 目录下的文件全部复制的 Runtime 目录中,并复制引擎的空工程示例 BlankProgram 工程到 Programs 目录中,并改个新名字 MyBlankProgram(UE4中各个Target名字全局不能冲突),新的结构如下
MyProject
|---MyProject.uproject
|---Config
|---Content
|---Source
|---Runtime // 新建的目录,将之前的 Source 目录下的内容直接平移进来
| |---MyProject.Target.cs
| |---MyProjectEditor.Target.cs
| |---MyProject
| |---MyProject.Build.cs
| |---MyProject.cpp
| |---MyProject.h
| |---MyProjectGameModeBase.cpp
| |---MyProjectGameModeBase.h
|---Programs // 新建的目录,用来放各种工具项目
|---MyBlankProgram
|---MyBlankProgram.Build.cs
|---MyBlankProgram.Target.cs
|---Private
| |---MyBlankProgram.cpp
| |---MyBlankProgram.h
|---Resources
|---Windows
|---BlankProgram.ico
右键 MyProject.uproject 文件,选择 Generate Visual Studio project files,生成工程文件,此时就会发现 MyBlankProgram 工程正确生成到 Solution 中的 Programs 目录下,如图
如果想自定义 MyBlankProgram 在 Solution 中的目录,可以打开 MyBlankProgram.target.cs 文件,在构造函数在给 SolutionDirectory
赋个自定义值,如
[SupportedPlatforms(UnrealPlatformClass.Desktop)]
public class MyBlankProgramTarget : TargetRules
{
public MyBlankProgramTarget(TargetInfo Target) : base(Target)
{
// other codes...
SolutionDirectory = "MyPrograms";
// other codes...
}
}
重新生成 Solution,此时 MyBlankProgram 就在 MyPrograms 目录下了,如图
注意点
在引擎的目录结构中,Engine/Source 目录下是有几个 Target.cs 文件的,如图
所以在我们的工程中,是否一样也可以把 MyProject.Target.cs 也放到 Source 根目录下呢?
答案是不行的,游戏工程搜索 Target.cs 文件和引擎是有些区别的,代码见 Source/Programs/UnrealBuildTool/System/NativeProjects.cs 中的 FindTargetFiles
函数。生成工程的时候,会搜索 uproject 文件所在目录下的所有 Target.cs 文件,但是如果在某一级目录搜索到了 Target.cs 文件,那就不会继续搜索这一级目录中的子目录了。所以如果将 MyProject.Target.cs 也放到 Source 下,那么搜索就会停在 Source 目录,所以 Source/Programs 目录中的 Target.cs 文件就会被忽略了
编译
此时编译 MyBlankProgram,会出现编译错误,如下
1>------ Build started: Project: MyBlankProgram, Configuration: Development_Program x64 ------
1>UnrealBuildTool : error : Unable to find project 'E:\Workspace\MyProject\MyBlankProgram.uproject'.
这个错误的原因是编译时调用 UBT 的命令行参数中有一个 -project 参数,参数值是有问题的,如图
有以下几种解决方法
使用 4.25 版本的引擎
4.25 中已经没有这个问题了
直接修改参数
在命令行中将 #(ProjectName) 直接改为 MyProject,如图
这种方法缺点是每次重新生成工程后都得改一遍
将工程新建到引擎目录下
第二种方法是直接将工程新建到引擎目录下,见之前的文章 UE4 关于工程目录结构的一个小技巧
将工程建到引擎目录下,生成工程时就不会在编译命令行中增加 -project 参数,此时会根据目录的层级关系在上级目录中搜索对应的 uproject
修改 UBT
最直接的方式就是改 UBT 源码,打开 Source/Programs/UnrealBuildTool/ProjectFiles/VisualStudio/VCProject.cs 文件,在 WriteConfiguration
函数中,新增一段代码,当是 IsForeignProject
的时候,优先使用命令行中传入的 uproject 文件路径,如图
其它编译错误
Program 的模块需要依赖于 LaunchEngineLoop.cpp 文件,由于现在将 Program 移到了引擎目录之外,所以在模块中添加 include 路径的地方也需要修改,打开 MyBlankProgram.Build.cs,将 PublicIncludePaths
和 PrivateIncludePaths
添加的路径拼上引擎路径,如图
结果
通过以上修改后,编译 MyBlankProgram,就会在 MyProject/Binaries/Win64 下看到生成的可执行文件,如图
运行结果如图
不过有一点不完美的就是,运行后日志,配置等文件的生成路径是在这里
这里的初始化代码见 FGenericPlatformMisc::ProjectDir
,在 Program 下写死的使用 Engine 目录,如图
如果想要修改,只能在自己的 Program 代码中,一开始初始化的时候调用 FPlatformMisc::SetOverrideProjectDir
改一下,如图
这样,Program 运行时生成的日志配置等就生成到正确的目录下,如图
非源码引擎编译 Program 工程
首先将上文的示例工程 MyProject 的引擎切换成安装版本的引擎,如图
此时生成工程会报错,报错信息如下
ERROR: Targets with a unique build environment cannot be built an installed engine
解决这个错误需要修改 MyBlankProgram.Target.cs,将 BuildEnvironment
改成 TargetBuildEnvironment.Shared
,如下
[SupportedPlatforms(UnrealPlatformClass.Desktop)]
public class MyBlankProgramTarget : TargetRules
{
public MyBlankProgramTarget(TargetInfo Target) : base(Target)
{
// other codes...
BuildEnvironment = TargetBuildEnvironment.Shared;
// other codes...
}
}
重新生成解决方案,修改后可以正常生成,如图
现在编译 MyBlankProgram,会遇到上文中同样的错误,如下
1>------ Build started: Project: MyBlankProgram, Configuration: Development_Program x64 ------
1>UnrealBuildTool : error : Unable to find project 'E:\Workspace\MyProject\MyBlankProgram.uproject'.
解决方法同上
继续编译,遇到新的错误
1>Creating makefile for MyBlankProgram (.uproject file is newer)
1>UnrealBuildTool : error : Program targets are not currently supported from this engine distribution.
这个错误的原因的安装版本的引擎能编译的配置是固定好的,并配置在 Engine/Config/BaseEngine.ini 的 [InstalledPlatforms]
中
解决这个问题的方法是将 Engine\Build\InstalledBuild.txt 文件重命名一下,UBT 是根据这个文件是否存在来判断是否是安装版本的引擎
此时再编译,就会正确编译 MyBlankProgram,可执行文件的输出目录是引擎目录 Engine/Binaries/Win64,如图
以上的步骤可以通过脚本来进行整合
生成工程
@ECHO OFF
SET EnginePath=E:\Epic Games\UE_4.24\Engine
CALL "%EnginePath%\Build\BatchFiles\Build.bat" -ProjectFiles -Project="%~dp0MyProject.uproject" -game -progress
PAUSE
编译工程
@ECHO OFF
SET EnginePath=E:\Epic Games\UE_4.24\Engine
REM 重命名 InstalledBuild.txt
IF EXIST "%EnginePath%\Build\InstalledBuild.txt" (
REN "%EnginePath%\Build\InstalledBuild.txt" InstalledBuild1.txt
)
CALL "%EnginePath%\Build\BatchFiles\Build.bat" MyBlankProgram Win64 Development -Project="%~dp0MyProject.uproject" -WaitMutex
REM 重命名 InstalledBuild.txt
IF EXIST "%EnginePath%\Build\InstalledBuild1.txt" (
REN "%EnginePath%\Build\InstalledBuild1.txt" InstalledBuild.txt
)
PAUSE
总结
在上文中解决这两个限制的方法,其实并不完美,但是目前好像也没有什么其它的解决方法