打包时路径过长的错误

在打包的时候遇到这个错误:

1
Couldn't save package,filename is too long

是因为某些资源在 Windows 上的绝对路径长度超过了 260 个字符,这是 NTFS 的限制。
所以,将项目路径移动到磁盘根目录,或者减少目录层级即可。
引擎中相关的代码在:

1
2
3
4
5
6
7
8
9
10
11
// Source/Editor/UnrealEd/Private/CookOnTheFlyServer.cpp(UE4.18.3)
// need to subtract 32 because the SavePackage code creates temporary files with longer file names then the one we provide
// projects may ignore this restriction if desired
const int32 CompressedPackageFileLengthRequirement = bConsiderCompressedPackageFileLengthRequirements ? 32 : 0;
const FString FullFilename = FPaths::ConvertRelativePathToFull(PlatFilename);
if (FullFilename.Len() >= (PLATFORM_MAX_FILEPATH_LENGTH - CompressedPackageFileLengthRequirement))
{
LogCookerMessage(FString::Printf(TEXT("Couldn't save package, filename is too long: %s"), *PlatFilename), EMessageSeverity::Error);
UE_LOG(LogCook, Error, TEXT("Couldn't save package, filename is too long :%s"), *PlatFilename);
Result = ESavePackageResult::Error;
}

而各个平台的 PLATFORM_MAX_FILEPATH_LENGTH 均定义在 Runtime/Core/Public 相关的平台下。
Windows 是使用的另一个宏WINDOWS_MAX_PATH

1
2
3
4
5
6
D:\UnrealEngine\Offical_Source\4.18\Engine\Source\Runtime\Core\Public\Windows\WIndowsPlatform.h:
57 #define PLATFORM_HAS_BSD_TIME 0
58 #define PLATFORM_USE_PTHREADS 0
59: #define PLATFORM_MAX_FILEPATH_LENGTH WINDOWS_MAX_PATH
60 #define PLATFORM_HAS_BSD_SOCKET_FEATURE_WINSOCKETS 1
61 #define PLATFORM_USES_MICROSOFT_LIBC_FUNCTIONS 1

WINDOWS_MAX_PATH这个宏定义在 Runtime/Core/Private/Windows/MinimalWindowsApi.h 中:

1
#define WINDOWS_MAX_PATH 260

显然 UE 并没有使用 Windows 提供的 MAX_PATH 宏,硬编码为了 260,即在 UE 中 Windows 上的文件路径最大长度为 260 个字符 (在启用bConsiderCompressedPackageFileLengthRequirements 时还要减去 32 个字符),虽然 Windows10 要 [移除 260 字符的限制](Microsoft removes 260 character limit for NTFS Path in new Windows 10 Insider Preview), 但是貌似 UE 没有跟进的打算 (UE4.22 Released 支持了长文件名的特性 (实验性))。
bConsiderCompressedPackageFileLengthRequirements 选项可以加在 Saved/Config/Windows/Engine.ini 下(默认为true):

1
2
[CookSettings]
bConsiderCompressedPackageFileLengthRequirements = true

这个配置是在 Cook 时会被加载用来判断是否考虑引擎生成的文件名长度:

1
2
3
4
5
6
7
8
// Source/Editor/UnrealEd/Private/CookOnTheFlyServer.cpp(UE4.18.3)
// need to subtract 32 because the SavePackage code creates temporary files with longer file names then the one we provide
bool UCookOnTheFlyServer::ShouldConsiderCompressedPackageFileLengthRequirements() const
{
bool bConsiderCompressedPackageFileLengthRequirements = true;
GConfig->GetBool(TEXT("CookSettings"), TEXT("bConsiderCompressedPackageFileLengthRequirements"), bConsiderCompressedPackageFileLengthRequirements, GEditorIni);
return bConsiderCompressedPackageFileLengthRequirements;
}

UCookOnTheFlyServer::SaveCookedPackage 中需要通过它来决定将系统支持的 MAX_PATH 减去 32 之后的结果,用来判断资源路径是否超出限制。

外部阅读: