UE4 UnrealBuildTool 生成 C++ 项目报错排查指南
在 Epic Launcher 里点下那个生成 C 项目的按钮命令行窗口一闪而过紧接着一行UnrealBuildTool.exe -projectfiles -project... -game -rocket -progress就怼在眼前下面还跟着一串让人摸不着头脑的报错——这个场景做 UE4 C 开发的人大概率都见过。它最烦的地方不在于修不好而在于它给的提示太干了没有任何一句人话告诉你缺了什么只把 UBT 被调起来时的完整参数列出来看上去像是工具在报参数实际是它在执行第一步就倒下了。这篇文章就是把这条报错从里到外拆一遍UnrealBuildTool.exe 到底负责什么-game -rocket -progress这三个词分别意味着什么UE4 生成 C 项目时依赖哪些外部环境哪些环节最容易断以及怎么一步步把问题钉死。不管你用的是 4.27 还是更老的 4.21是全新装机的引擎还是跑了半年的老项目都能在里面找到对应的排查路径。1. 先弄明白这行命令到底在干什么1.1 UnrealBuildTool 是 UE4 的工具链总调度很多人把 UnrealBuildTool 理解成一个编译器这个认知偏差会直接导致排查方向跑偏。UBT 本身不编译一个字符的 C它是整套构建流程的调度中枢写 C# 的跑在 .NET 上。它干的活大致分三类第一类是读配置把.uproject、.uplugin、Target.cs、Build.cs这些描述性文件解析成一张完整的模块依赖图第二类是选工具根据引擎版本、目标平台、当前安装的 Visual Studio 版本决定调用哪一套 MSVC 编译器、哪个版本的 Windows SDK第三类是下发任务把编译、链接、资源拷贝的实际动作交给 MSBuild 和平台的工具链去执行。理解这一点很关键因为报错发生在第三类之前的任一环节时你看到的现象都是命令行列了一串参数然后退出。UBT 在正式干活之前要先完成自我检查引擎路径对不对、目标平台支持不支持、有没有可用的编译工具链、项目描述文件有没有语法错误。任何一项不通过它就把调用它的那行参数原样打出来然后中断。所以这行报错信息本质上是案发现场的门牌号不是案情描述真正的线索在日志里。1.2-game、-rocket、-progress三个参数逐个拆解这三个词看着像乱码其实是 UBT 的命令行开关每个都有明确语义看懂了能帮你判断它是在哪一步挂的。-game表示这次构建的目标类型是 Game而不是 Engine。UE4 的项目文件里Target.cs会声明Type TargetType.Game或者TargetType.Editor-game相当于在命令行层面确认我这次处理的是游戏项目引擎的模块当作外部依赖不需要一起重新编译。如果这个参数选错UBT 会尝试把整个引擎源码纳入构建范围在 Launcher 安装版的引擎上这必然失败因为引擎目录里根本没有完整的源码和中间文件。-rocket是火箭版的意思指通过 Epic Launcher 安装的二进制分发版引擎和从源码编译的引擎相对。带上这个开关UBT 就会按引擎是只读外部依赖的模式工作它不会去写引擎目录下的任何构建产物所有中间文件都放到项目自己的Intermediate里。这一点非常容易踩坑如果你的引擎目录被放在C:\Program Files\下而 UBT 又没识别出这是 rocket 版它会尝试往引擎目录写文件然后因为权限不足或者目录只读而失败。-progress只是让它把进度信息输出到标准输出供 IDE 或调用方画进度条用它本身不影响构建结果但少了它你在命令行里会看到长时间卡住的假象。除了这三个实际调用里往往还带着-projectxxx.uproject这个才是真正指定目标项目的参数。所以当你在报错里看到-game -rocket -progress却看不到-project或者-project指向的路径明显不对那基本可以确定问题出在调用方通常是 UnrealVersionSelector 或者引擎的 batch 脚本而不是 UBT 内部。1.3 为什么报错信息里只有参数没有原因UBT 的设计哲学是详细日志落盘控制台只留摘要。它把所有诊断信息写进日志文件控制台只负责告诉你我启动了、我用的是这些参数、我失败了。所以你光盯着弹窗是没有用的必须去翻日志。这一点和很多新手从其他语言工具链带过来的直觉不一样VS 编译失败会直接在输出窗口告诉你第几行缺头文件UBT 不会它只会在日志里用几百行描述它检查了什么、哪些通过了、哪些没通过。顺着这个逻辑排查的第一步永远不是重装而是找到日志。这个顺序搞反了你会白白浪费几个小时甚至重装完发现问题依旧。下面几节按依赖层次从外到内讲先是环境再是工具链最后是项目自身。2. 环境依赖缺失九成报错都出在这一层2.1 Visual Studio 的 C 工作负载没装全UE4 生成 C 项目这件事本质上就是造一个能被 Visual Studio 打开的解决方案所以 UBT 第一件要确认的事就是这台机器上有没有能让它调用的 C 编译工具链。注意这里说的不是装没装 Visual Studio而是装没装 Visual Studio 里的 C 组件。用 VS Installer 装 VS 的时候工作负载那一页默认勾选的往往是 .NET 桌面开发或者通用 Windows 平台开发使用 C 的桌面开发这个工作负载经常被漏掉。漏掉它的后果就是VS 装好了能开、能写 C#但 MSVC 编译器、Windows SDK、CMake 工具、vcpkg 一个都没有。UBT 通过vswhere查询时会按组件 ID 过滤找的是Microsoft.VisualStudio.Component.VC.Tools.x86.x64这一类标记找不到就直接判定没有可用的 Visual Studio 实例。修复方式很直接打开 Visual Studio Installer找到已安装的版本点修改在工作负载页勾上使用 C 的桌面开发右侧安装详细信息里确认这几项都在MSVC v142对应 UE4.23 之后的版本或 v141对应 4.21/4.22、Windows 10 SDK、C 通用工具、用于 Windows 的 C CMake 工具。装完之后不需要重启但一定要重新生成一次项目文件。这里有个容易被忽视的点UE4 对 VS 版本是有要求的不是越新越好。4.21 到 4.26 这一段官方支持 VS2017 15.6 以上和 VS20194.27 官方推荐 VS2019 16.4 及以上装 VS2022 需要额外的兼容处理。如果你机器上同时装了 VS2019 和 VS2022UBT 按注册表顺序选可能恰好选到它不支持的那个然后报出一堆和工具集相关的错。这种情况下要么在命令行用-2019这类参数强制指定要么老老实实把不支持的版本先卸掉。2.2 MSVC 工具集与 Windows SDK 版本错配就算工作负载装全了工具集版本和 SDK 版本对不上UBT 一样会中断。新版 UBT 检查工具链时会读Engine/Source/Programs/UnrealBuildTool/Platform/Windows/下的 UEToolChain 配置里面写死了支持的工具集范围和推荐的 SDK 版本。比如某个引擎版本明确要求 Windows 10 SDK 10.0.18362 或更高而你机器上只有 10.0.17763那它在做环境检查时就会判定不满足。判断方法很土但有效打开C:\Program Files (x86)\Windows Kits\10\Include\看看里面有几个版本号文件夹记下最大的那个。再打开 VS Installer 的单个组件页看 MSVC v142 的版本号。然后对比引擎版本的要求。4.27 一般要求 Windows 10 SDK 版本不低于 10.0.18362MSVC v142 建议 14.29 以上UE4.26 的要求略低一些。装 SDK 的时候如果顺手装了一堆 8.1、10.0.17134 之类的旧版本UBT 有可能在自动选择时挑到旧的导致编译到一半报缺头文件。还有一种情况是SDK 装了但没装全。Windows SDK 的安装项里除了头文件和库还有 Windows SDK for Desktop C x86 and x64 这类组件必须勾上光装 UWP 那部分是没用的。UBT 找的是um、shared、ucrt这几个目录下的内容少一个都会出问题。2.3 .NET Framework / .NET 运行时版本对不上UnrealBuildTool 是 C# 写的它需要运行时的支持。这里有个分水岭UE4.24 之前Windows 上的 UBT 跑在 .NET Framework 上一般要求 4.6.2 或更高从 4.24 开始Epic 把 UBT 迁移到了 .NET Core4.24 用的是 3.1后续版本逐步跟进到更新的 .NET。这个变化带来的直接影响是老引擎需要 .NET Framework 更新新引擎需要独立的 .NET 运行时而这两者并不通用。如果你在 4.24 以后的引擎上遇到找不到 UnrealBuildTool.dll或者It was not possible to find any compatible framework version这类报错八成是缺 .NET 运行时。判断方法是在命令行里敲dotnet --list-runtimes如果提示命令不存在或者列表里没有对应的主版本那就得去装。装的时候注意区分 x64 和 x86UE4 的 UBT 在 Windows 上跑的是 x64 版本。老引擎的情况反过来.NET Framework 4.6.2在很多 Windows 10 初版系统里是默认带的但如果你用的是精简版系统镜像或者手动关过 Windows 功能它可能被禁用了。这种情况在启用或关闭 Windows 功能里找到 .NET Framework 4.x 相关项勾上即可卸载再重装 VS 反而解决不了。2.4 一个常见误区装 Visual C Redistributable 解决不了生成问题网上搜这个报错很容易搜到装 Visual C Redistributable的建议然后你装了Microsoft Visual C 2019 Redistributable Package (x64)重启问题照旧。原因很简单Redistributable 是运行时库用来跑已经编译好的程序的跟编译过程没关系。UBT 报的是我找不到编译器不是我的程序跑不起来缺 dll。这个误区之所以流传广是因为很多错误提示里确实会提到Microsoft Visual C 14.0 or greater is required但那通常是 Python 装某类扩展包时 pip 报的错语境完全不同。在 UE4 的语境下看到类似措辞先别急着装 Redistributable先把 UBT 的日志翻出来确认它到底缺什么。真要说 Redistributable 有什么用那是引擎本身或者你打包出来的游戏运行时要装的东西和生成 C 项目是两条线。3. 手把手排查从日志到修复3.1 第一站UBT 日志文件UBT 的日志位置分两种情况。较新的版本4.24 之后在C:\Users\你的用户名\AppData\Local\UnrealBuildTool\Log.txt较早的版本在%APPDATA%\Unreal Engine\UnrealBuildTool\Log.txt。如果你在资源管理器里看不到 AppData需要先在查看里勾上隐藏的项目。打开之后直接跳到文件末尾因为 UBT 是顺序执行的最后一次失败的原因一定在最后几十行。你要找的关键词有这么几类ERROR:开头的行是第一优先级No Visual Studio installation found或者Unable to find any Visual Studio installation说明是 VS 检测失败Could not find the Windows SDK说明是 SDK 问题Failed to load加 dll 名说明是 .NET 或依赖文件缺失Access to the path ... is denied说明是权限问题。日志里有意思的一点是UBT 会把所有找到的 VS 实例都列出来包括它们的安装路径和组件清单。你可以借此确认它到底看见了几个 VS、选中了哪一个、那个实例里有没有 C 工具。这一步的信息量比任何网上搜来的教程都大因为它是针对你这台机器的实际状态输出的。3.2 第二站用 vswhere 确认 VS 是否被识别想跳过日志直接验证 VS 的注册状态可以用微软官方的vswhere.exe它在每个 VS 安装的 Installer 目录下都有C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe。在命令行里跑这条C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe -latest -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath如果返回一行路径说明 C 工具组件是有的UBT 理论上应该能找到如果什么都不返回说明 C 组件确实缺回去补装。想看全部实例就把-latest去掉C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe -products * -format json输出的 JSON 里会有每个实例的installationPath、installationVersion、displayName。如果这里出现了 VS2022 而没有 VS2019而你的引擎是 4.22那基本可以确定是版本不匹配。另外还可以查注册表HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\VisualStudio\SxS\VS7这个键下面会列出所有被系统认可的 VS 版本和路径UBT 早期版本就是从这里取信息的。注册表里缺项、路径指向已经不存在的目录都会导致识别失败。3.3 第三站命令行手动复现把错误钉死图形界面点按钮最容易丢信息因为窗口一闪就没了。直接开一个命令行窗口手动把 UBT 调起来让它把完整输出吐在屏幕上。以 4.27 为例C:\Program Files\Epic Games\UE_4.27\Engine\Binaries\DotNET\UnrealBuildTool.exe ^ -projectfiles ^ -projectD:\Projects\MyGame\MyGame.uproject ^ -game -rocket -progress -log这里我加了-log它会额外把详细日志打到标准输出方便你直接看。4.24 之后的引擎如果UnrealBuildTool.exe不存在改成用 dotnet 跑 dlldotnet C:\Program Files\Epic Games\UE_4.27\Engine\Binaries\DotNET\UnrealBuildTool\UnrealBuildTool.dll ^ -projectfiles ^ -projectD:\Projects\MyGame\MyGame.uproject ^ -game -rocket -progress如果你是在引擎根目录下操作也可以直接用引擎自带的批处理Engine\Build\BatchFiles\GenerateProjectFiles.bat -projectD:\Projects\MyGame\MyGame.uproject -game -rocket -progress。这个脚本会把环境变量、工作目录都设置好是排除调用方传参错误这个变量的最好方式。手动跑一遍的意义在于你能亲眼看到失败发生在第几秒、停在哪句话而不是只看到一个弹窗。3.4 修复动作补装组件、指定版本、重建项目文件确认问题之后修复动作通常是下面几种的组合。补装 VS 组件打开 Visual Studio Installer修改已安装实例勾上使用 C 的桌面开发在单个组件页确认 MSVC 工具集和 Windows SDK 都在。装完之后跑一次vswhere验证。强制指定 VS 版本如果你不想卸掉多余的 VS可以在命令行加-2019或者-vs2022这类开关也可以在引擎的BuildConfiguration.xml里配置。这个文件的位置在%APPDATA%\Unreal Engine\UnrealBuildTool\BuildConfiguration.xml没有就自己建一个内容长这样?xml version1.0 encodingutf-8 ? Configuration xmlnshttps://www.unrealengine.com/BuildConfiguration WindowsPlatform CompilerVersion14.29.30133/CompilerVersion WindowsSdkVersion10.0.19041.0/WindowsSdkVersion /WindowsPlatform /ConfigurationCompilerVersion填 MSVC 工具集版本WindowsSdkVersion填 SDK 版本两个都要和你机器上实际装的完全一致写错一位都不行。这个方法的好处是不动系统环境坏处是换机器要重新配。重建项目文件改完环境之后先把项目目录下的Binaries、Intermediate、.vs、*.sln全部删掉再右键.uproject选 Generate Visual Studio project files。这一步很多人会忘结果旧的 sln 里还缓存着错误路径打开后仍然报错误以为修复没生效。4. 路径、权限、项目自身的问题4.1 中文路径、空格、超长路径UBT 和 MSBuild 对路径的容忍度比想象中低。项目路径里出现中文、日文、韩文等非 ASCII 字符很容易在某个环节被编码转换搞坏表现为文件明明在它就是找不到。路径里带空格虽然大多数情况下能处理但当路径出现在批处理脚本或 Makefile 风格的配置文件里时空格是最经典的坑。还有长度问题。Windows 的传统路径上限是 260 个字符UE4 的构建产物层级很深Engine\Intermediate\Build\Win64\UE4Editor\Development\ModuleName\...这种嵌套下来如果起点本身就深很容易超限。超限之后的表现五花八门有时是文件找不到有时是写入失败。最稳的做法是把项目放在盘符根目录下路径全英文、无空格、尽量短比如D:\UEProjects\MyGame。同时把引擎也放在非系统盘避免C:\Program Files这种需要管理员权限又有空格的位置。引擎装在 Program Files 下如果 UBT 判断不出 rocket 版还会去尝试写引擎目录然后卡在权限上。4.2 Intermediate、Saved、Binaries 残留与 .vs 目录UBT 是增量构建的它会读Intermediate里缓存的依赖信息来判断哪些模块需要重新编译。这个缓存在环境变化之后经常失效表现就是环境明明修好了项目还是打不开。所以只要动过 VS、动过 SDK、动过引擎版本第一件事就是清Intermediate和Binaries。.vs目录是 VS 自己生成的状态缓存里面有智能提示的数据库、调试配置、打开的文档记录。这个目录和 UBT 没直接关系但当 sln 被重新生成而.vs还是旧的时VS 打开项目会各种抽风包括提示找不到某个.vcxproj。删掉它零成本重建一次就行。另外Saved目录里有一些自动生成的配置和日志一般情况下不用删但如果项目曾经在另一台机器上、另一个引擎版本下打开过Saved\Config里的路径引用可能指向不存在的目录间接导致插件加载失败。这种情况删掉Saved也能解决代价是丢掉一些个人设置。4.3 EngineAssociation 指向错误的引擎版本.uproject文件是纯 JSON里面有个字段叫EngineAssociation。它的值可能是版本号比如4.27也可能是一个 GUID源码版引擎用。UBT 会拿这个值去注册表HKEY_LOCAL_MACHINE\SOFTWARE\EpicGames\Unreal Engine\下面找对应的安装路径如果找不到就会报引擎版本未安装或者直接静默失败。你可以手动打开.uproject看这个字段。如果写的是4.26但你实际装的是4.27要么改字段要么用右键菜单里的 Switch Unreal Engine Version 重新绑定。这个右键菜单依赖UnrealVersionSelector.exe在引擎的Engine\Binaries\Win64\目录下如果它自己也没注册好可以手动执行一次UnrealVersionSelector.exe /register。还有一种情况是项目里启用了第三方插件而插件依赖的模块在当前引擎版本里不存在。这种情况下 UBT 的报错通常指向某个.Build.cs文件说找不到引用的模块。常见于 VR 外设相关的插件——启用了某个设备映射插件但对应的 SDK 没装或者插件版本和引擎版本不匹配。处理方式是先把.uproject里那个插件的Enabled改成false确认项目能生成之后再单独解决插件依赖。4.4 杀软、OneDrive 同步与目录权限有几个玄学问题值得单独说。一是杀毒软件UBT 在编译期间会大量读写临时文件某些安全软件的行为监控会拦住这些操作表现为编译到某个模块突然失败错误信息还很含糊。遇到这种就把项目目录和引擎目录加到白名单里。二是 OneDrive 或其他同步盘把项目放在同步目录下同步进程会频繁锁定文件导致编译时文件被占用或者刚写进去就被同步走。同理放在网络映射盘上也一样。UE4 项目动辄几十 GB本来也不适合放在同步目录里。三是目录权限如果项目目录是从别的机器拷来的或者曾经用管理员权限创建过当前用户可能只有读权限。表现是 UBT 报Access to the path xxx is denied。解决方法是右键目录 → 属性 → 安全确认当前用户有完全控制权实在不行就整个目录复制一份到新位置。5. 常见报错速查表报错关键词大概率原因优先处理动作No Visual Studio installation foundVS 未装或未装 C 工作负载VS Installer 修改勾使用 C 的桌面开发Unable to find any Visual Studio installationVS 装了但组件 ID 不匹配用 vswhere 验证VC.Tools.x86.x64Could not find the Windows SDKWindows SDK 缺失或版本过低装 10.0.18362 以上勾 Desktop C 组件It was not possible to find any compatible framework version缺 .NET 运行时对应版本装 .NET Core / .NETCould not load file or assembly.NET Framework 版本不符或被禁用启用 .NET Framework 4.x 功能Access to the path ... is denied目录权限不足或引擎目录只读检查目录安全设置移动项目位置UnrealBuildTool.exe找不到引擎安装不完整Launcher 里验证引擎文件完整性报错指向某个.Build.cs插件依赖缺失或版本不符先禁用该插件再逐步恢复引擎版本未安装EngineAssociation与实装版本不符改字段或右键 Switch Engine Version编译到一半随机失败杀软拦截或同步盘干扰加白名单项目移出同步目录这张表只能帮你定位方向具体到每台机器还得看日志。同一个报错在不同环境下的成因可能完全不同尤其是找不到编译器这一类可能是 VS 没装也可能是装了但版本不被支持还可能只是注册表被清理软件动过。6. 实操心得几件让我少走弯路的事先说一个我吃过亏的顺序问题。最开始遇到这个报错我的第一反应是重装引擎重装完发现问题依旧又去重装 VS折腾了大半天。后来才明白正确的顺序永远是先看日志、再验证环境、最后才动手改。日志只要三十秒就能看完重装一次引擎要半小时以上而且大概率修不对。现在我的习惯是任何 UBT 相关的报错先开日志找到第一个ERROR再决定动哪里。第二个心得是关于版本组合的。UE4 的版本和 VS 的版本匹配关系不是随便搭的官方文档里有一张对应表值得存下来。4.21 到 4.23 这个区间VS2017 和 VS2019 都能用4.24 到 4.26 偏向 VS20194.27 对 VS2019 的支持最完整。如果机器上装了多个 VS要么用BuildConfiguration.xml指定要么把不用的卸掉。我个人的做法是每台开发机只留一个 VS 大版本虽然牺牲了一点灵活性但省掉了大量它到底选了哪个的排查时间。第三个是缓存清理的粒度。很多人一听要清缓存就把Intermediate、Binaries、Saved、.vs全删一遍。实际上这四个目录的作用不同删错了会丢掉有用的东西。Intermediate和Binaries是构建产物随便删.vs是编辑器状态删了只影响智能提示的首次加载时间Saved里除了日志还有项目设置和自动保存删之前最好确认一下。我一般只删前两个只有问题实在诡异时才动后两个。第四个是记录环境快照。每配好一台能正常生成 C 项目的机器我会把vswhere -format json的输出、dotnet --list-runtimes的结果、Windows Kits\10\Include下的版本号连同引擎版本一起存到项目的Docs目录里。下次换机器或者出问题时对照一下就大概知道差在哪。这个习惯看起来麻烦实际能省下大量重复摸索。最后一个和插件有关。项目里启用的插件越多UBT 在解析依赖阶段要做的事就越多出错的概率也就越高。我的建议是新建项目时保持最小插件集需要什么再加什么加完之后立刻验证一次能否生成项目文件。尤其是和外接设备、VR、专用硬件相关的插件它们往往依赖额外的 SDK 或者驱动装上插件不等于能编译。一旦发现加了某个插件之后开始报错第一件事就是把它在.uproject里禁用掉确认最小可运行状态再一个一个往回加。这样即使某个插件有问题你也能立刻定位到是谁而不是对着一堆模块名猜。