检测是否为安装版引擎的方法

在 EpicGameLauncher 安装的引擎版本是不能通过 UnrealBuildTool.exe -ProjectFiles "ProgramProjectName" 来创建 TargetProgram的项目的,会提示下列错误:

1
ERROR: UnrealBuildTool Exception: A game project path was not specified, which is required when generating project files using an installed build or passing -game on the command line

这个异常在 UBT 里的相关代码在ProjectFileGenreator.cs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
// ProjectFileGenreator.cs

protected virtual void ConfigureProjectFileGeneration( String[] Arguments, ref bool IncludeAllPlatforms )
{
// ...
else switch(CurArgument.ToUpperInvariant() )
{
// ...
case "-GAME":
// Generates project files for a single game
bGeneratingGameProjectFiles = true;
break;
// ...
}
// ...

if(bGeneratingGameProjectFiles || UnrealBuildTool.IsEngineInstalled() )
{
if (OnlyGameProject == null)
{
throw new BuildException("A game project path was not specified, which is required when generating project files using an installed build or passing -game on the command line");
}

GameProjectName = OnlyGameProject.GetFileNameWithoutExtension();
if (String.IsNullOrEmpty(GameProjectName))
{
throw new BuildException("A valid game project was not found in the specified location (" + OnlyGameProject.Directory.FullName + ")");
}

bool bInstalledEngineWithSource = UnrealBuildTool.IsEngineInstalled() && DirectoryReference.Exists(UnrealBuildTool.EngineSourceDirectory);

bIncludeEngineSource = bAlwaysIncludeEngineModules || bInstalledEngineWithSource;
bIncludeDocumentation = false;
bIncludeBuildSystemFiles = false;
bIncludeShaderSource = true;
bIncludeTemplateFiles = false;
bIncludeConfigFiles = true;
IncludeEnginePrograms = bAlwaysIncludeEngineModules;
}
}

可以看到,if这里如果传递给 UBT-game参数并且是引擎是安装版本 (EpicGameLauncher) 时会检测有没有传入 project 参数,如果没有就会抛异常。
正常的 UBT 调用命令:

1
UnrelBuildTool.exe -ProjectFiles -project="D:\UnrealProjects\UEProject.uproject" -game

这种普通的 Game 参数在 UBT 里面是不会抛异常的。但是用生成 Program 的命令来调用 UBT,安装版引擎就会抛异常:

1
UnrelBuildTool.exe -ProjectFiles ProgramName

根据上面 ProjectFileGenreator.cs 的检测代码,我们要做到的是把 UnrealBuildTool.IsEngineInstalled() 获取的结果变为 false.
继续跟代码:UnrealBuildTool.IsEngineInstalled()获得的是 UnrealBuildTool 中的一个 bool 变量bIsEngineInstalled

1
2
3
4
5
6
7
8
9
// UnrealBuildTool.cs
static public bool IsEngineInstalled()
{
if (!bIsEngineInstalled.HasValue)
{
throw new BuildException("IsEngineInstalled() called before being initialized.");
}
return bIsEngineInstalled.Value;
}

查找引用发现在 GuardedMain 里有设置 bIsEngineInstalled 这个变量的地方:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// UnrealBuildTool.cs
private static int GuardedMain(string[] Arguments)
{
// ...
try{
// ...
foreach (string Argument in Arguments)
{
string LowercaseArg = Argument.ToLowerInvariant();
if (LowercaseArg == "-installed" || LowercaseArg == "-installedengine")
{
bIsEngineInstalled = true;
}
else if (LowercaseArg == "-notinstalledengine")
{
bIsEngineInstalled = false;
}
}
if (!bIsEngineInstalled.HasValue)
{
bIsEngineInstalled = FileReference.Exists(FileReference.Combine(RootDirectory, "Engine", "Build", "InstalledBuild.txt"));
}
// ...
}
}

从代码可以看到,UBT 对是不是安装版引擎的检测有三种方法:

  1. 传入参数是否有 -installled-installedengine
  2. 传入参数是否有-notinstallengine
  3. 判断引擎路径 Engine\Build 下是否具有 InstalledBuild.txt 文件

(说是三种其实也就是两种,就算指定了 -notinstallengine 也是要判断存不存在 Engine\Build\InstalledBuild.txt 这个文件)
而且检测的顺序是这样的:

1
-installled > -installedengine > -notinstalledengine > Engine\Build\InstalledBuild.txt

所以,当我想要让 UBT 认为我的引擎版本不是安装版,有两种办法:

  1. 对 UBT 的调用传入 -notinstalledengine 参数,并且删掉 Engine\Build 目录下的 InstalledBuild.txt 文件
  2. 对 UBT 的调用不传入 -installled-installedengine参数,并且删掉 Engine\Build 目录下的 InstalledBuild.txt 文件

:UBT 里还有下面两种检测:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// UnrealBuildTools.cs
static public bool IsEnterpriseInstalled()
{
if(!bIsEnterpriseInstalled.HasValue)
{
bIsEnterpriseInstalled = FileReference.Exists(FileReference.Combine(EnterpriseDirectory, "Build", "InstalledBuild.txt"));
}
return bIsEnterpriseInstalled.Value;
}
static public bool IsProjectInstalled()
{
if (!bIsProjectInstalled.HasValue)
{
bIsProjectInstalled = FileReference.Exists(FileReference.Combine(RootDirectory, "Engine", "Build", "InstalledProjectBuild.txt"));
}
return bIsProjectInstalled.Value;
}