UE4 Cook流程中IdenticalUncookedPackages的含义,以及一种“资源未打包”情形的解释

背景

某次调整入包地图时,发现某张地图没有成功打包。于是调查并做此记录。

操作过程:

第一次构建时,配置DefaultGame.ini如下:

+MapsToCook=(FilePath="M的路径")

第二次构建时,配置DefaultGame.ini如下:

; (注释掉的意思)+MapsToCook=(FilePath="M的路径")

+DirectoriesToNeverCookWildcard=M的路径

第三次构建时,配置DefaultGame.ini如下:

+MapsToCook=(FilePath="M的路径")

; +DirectoriesToNeverCookWildcard=M的路径

表现:第一次构建时,包体里有M;第二次构建时,包体里没有M;第三次构建时,包体里依然没有M,预期有M,因此属于错误情况。

接下来我们看为何M在第三次时没能成功Cook。

结论先行

1、根据 《IgnoreIniSettingsOutOfDate开关的介绍》 ,由于我所在的项目里,打开了 IgnoreIniSettingsOutOfDate ,因此不会在 "项目的打包配置(尤其是Cook设置)发生重大变更",走UE4自带的 "清理整个 Saved目录" 的逻辑。

2、DirectoriesToNeverCookWildcard 的反注释,属于"重大变更" ,因此需要清理Saved目录。

3、解决方法:

● 以后都关闭 IgnoreIniSettingsOutOfDate ,遇到这类问题就不用担心出问题。

● 保持 IgnoreIniSettingsOutOfDate ,当 DirectoriesToNeverCookWildcard 反注释时,主动清理 Saved目录(搞清楚所有原理后,我们能更加精确地得知,只需要清理 Saved/Cooked 即可)。

接下来我们看看原理细节。

IdenticalUncookedPackages

在真正开始Cook前,UE4会根据上一次的 原始资源状态(记录在 D:\我的工程\Saved\Cooked\平台名LinuxServer\我的工程名\Metadata\DevelopmentAssetRegistry.bin )(代码见 PreviousPackageData),和当前的资源状态,做比较,其中一种情形如下,当原始资源哈希没有变化,且曾经没有真正产出到 Saved/Cooked 目录中 (PreviousPackageData->DiskSize < 0)时,该资源归属于 IdenticalUncookedPackages 。

复制代码
// 位于void FAssetRegistryGenerator::ComputePackageDifferences(......)   EngineSource\Engine\Source\Editor\UnrealEd\Private\Commandlets\AssetRegistryGenerator.cpp
......
else if (CurrentPackageData->PackageGuid == PreviousPackageData->PackageGuid)
{
	if (PreviousPackageData->DiskSize < 0)
	{
		IdenticalUncookedPackages.Add(PackageName);
	}
	else
	{
		IdenticalCookedPackages.Add(PackageName);		
	}
}
......

而从下面的代码可以看出IdenticalUncookedPackages 的含义------此资源会直接跳过cook,直接加入到 CookedPackages队列(已完成)、KeptPackages队列(未变化的资源队列 | 增量跳过队列)中,且++NumMarkedFailedSaveKept 也预示着,这个资源此次未能保存成功。

直白来说:"一旦因某种合理的原因没有Cook该资源",且Cook全流程完成了,那么后续构建遇到此资源,也会直接跳过,不会考虑Cook该资源。直到此原始资源MD5发生变更。

复制代码
// 位于 void UCookOnTheFlyServer::PopulateCookedPackagesFromDisk(......) EngineSource\Engine\Source\Editor\UnrealEd\Private\CookOnTheFlyServer.cpp

		// Register identical uncooked packages from previous run
		for (FName UncookedPackage : IdenticalUncookedPackages) // 直接认为 kept(也就是不用cook,直接放入到 cooked中)
		{
			const FName UncookedFilename = PackageNameCache->GetCachedStandardPackageFileFName(UncookedPackage);

			TArray<FName> PlatformNames;
			PlatformNames.Add(PlatformFName);

			ensure(PackageTracker->CookedPackages.Exists(UncookedFilename, PlatformNames, false) == false);

			PackageTracker->CookedPackages.Add(FFilePlatformCookedPackage(UncookedFilename, MoveTemp(PlatformNames)));
			KeptPackages.Add(UncookedPackage);
			++NumMarkedFailedSaveKept;
		}

代入到背景case中则是:

● "某种合理的原因"------背景介绍里第二次构建的配置,添加了 DirectoriesToNeverCookWildcard。

● "Cook全流程完成了"------背景介绍里第二次构建是成功的构建,并不属于异常。

● "后续构建"------第三次构建。

因此解决方法是删除 Saved/Cooked ,目的是让所有Cooked产物都删除掉,且让 PreviousPackageData 也删除掉(失效掉),因为PreviousPackageData 即 D:\我的工程\Saved\Cooked\平台名LinuxServer\我的工程名\Metadata\DevelopmentAssetRegistry.bin 也在 Saved/Cooked 中。

最佳实践

当你的工程很大,打开了 IgnoreIniSettingsOutOfDate 时,并且修改了 "进包配置",例如调整了 DirectoriesToNeverCookWildcard,那么需要删除掉 Saved/Cooked 。这个过程最好是自动化。

相关推荐
上山老人5 天前
UE4布娃娃约束修改
ue4
Yuk丶10 天前
厌倦了假AI对话?用本地大模型给UE注入真智能(已开源!)
c++·人工智能·开源·ue4·游戏程序·ue4客户端开发
emplace_back11 天前
UE 使用UE4PrereqSetup_x64.exe一键安装依赖
ue4
Yuk丶15 天前
LPM的AI 角色三大核心技术实现:长效记忆、人格锁定、低延迟口语化
人工智能·ai·ue4·虚幻·ue4客户端开发
归真仙人17 天前
【UE】Lightmass可执行文件已经过时
ue5·游戏引擎·ue4·虚幻·unreal engine
DoomGT17 天前
Design - 一些免费图标网站
ue5·ue4·虚幻·虚幻引擎·unreal engine
归真仙人21 天前
【UE】VR一体机转场
ue5·ue4·vr·虚幻引擎·unreal engine
洋洋061721 天前
UE4/UE5 引擎常见面试题总结(1)
ue5·ue4
Yuk丶24 天前
UE4 与 UE5:技术差异深度解析
c++·ue5·游戏引擎·ue4·游戏程序·虚幻
晴夏。1 个月前
unlua实现原理
游戏·ue5·ue4·lua·ue·unlua