UE5 非uasset资产Chunk/Pak 划分踩坑笔记

前言

引擎版本 UE 5.32源码
需求:打包时将非uasset资产(如Lua脚本)单独打入指定chunk包

遇到过的问题:

  • PakFileRules文件被排除
  • 设置了指定的chunkId但无效

流程

修改DefaultGame.ini,添加允许的配置文件目录

在这里插入图片描述

对AutomationTool\AutomationUtils\DeploymentContext.cs进行修改

将pakfilerules.ini注释掉,否则所有pakfilerules文件会被排除

对Scripts/CopyBuildToStagingDirectory.Automation.cs 进行修改

private struct PakFileRules
{
	// Name of config section
	public string Name;

	// Combined filter from all +Files= entries
	public FileFilter Filter;

	// An alternative and efficient way to match files
	public HashSet<string> ExactFileMatches = new();

	// To use exact file match or file filter
	public bool bUseExactFilePathMatch = false;

	// Rather to exclude entirely from paks
	public bool bExcludeFromPaks = false;

	// Rather to allow overriding the chunk manifest, if false will only modify loose files
	public bool bOverrideChunkManifest = false;

	// Whether pak file rule is disabled
	public bool bDisabled = false;

	// List of pak files to use instead of manifest
	public List<string> OverridePaks = new();

	// Whether this rule is defined for content-on-demand
	public bool bOnDemand = false;

	public bool bStageLoose = false;

	// Encryption key
	public string EncryptionKeyGuid = "";

	public PakFileRules()
	{
		Name = "";
		Filter = new FileFilter();
	}

	public static bool IsMatch(PakFileRules PakRules, KeyValuePair<string, string> StagingFile)
	{
		bool bMatched = !PakRules.bDisabled &&
			((!PakRules.bUseExactFilePathMatch && PakRules.Filter != null && PakRules.Filter.Matches(StagingFile.Key)) ||
			(PakRules.bUseExactFilePathMatch && PakRules.ExactFileMatches != null && PakRules.ExactFileMatches.Contains(StagingFile.Value)));
		
		return bMatched;
	}
};

/// <summary>
/// Reads Default/BasePakFileRules.ini and returns all PakFileRules objects that apply for this deployment
/// </summary>
/// <param name="Params"></param>
/// <param name="SC"></param>
private static List<PakFileRules> GetPakFileRules(ProjectParams Params, DeploymentContext SC)
{
	// if we want to ignore the rules while staging, just don't read any rules in!
	bool bWarnedAboutMultipleTargets = false;
	bool bFoundConfig = false;

	List<ConfigFile> ConfigFiles = new List<ConfigFile>();
	FileReference BaseConfigFileReference = FileReference.Combine(SC.EngineRoot, "Config", "BasePakFileRules.ini");
	if (FileReference.Exists(BaseConfigFileReference))
	{
		ConfigFiles.Add(new ConfigFile(BaseConfigFileReference));
		bFoundConfig = true;
	}

	FileReference ProjectConfigFileReference = FileReference.Combine(SC.ProjectRoot, "Config", "DefaultPakFileRules.ini");
	if (FileReference.Exists(ProjectConfigFileReference))
	{
		ConfigFiles.Add(new ConfigFile(ProjectConfigFileReference));
		bFoundConfig = true;
	}

	if (!bFoundConfig)
	{
		return null;
	}

	bool bChunkedBuild = SC.PlatformUsesChunkManifests && DoesChunkPakManifestExist(Params, SC);

	ConfigHierarchy PakRulesConfig = new ConfigHierarchy(ConfigFiles);

	List<PakFileRules> RulesList = new List<PakFileRules>();
	foreach (string SectionName in PakRulesConfig.SectionNames)
	{
		Logger.LogInformation("Building PakFileRules for Section {0}", SectionName);

		bool bOnlyChunkedBuilds = false;
		if (!PakRulesConfig.TryGetValue(SectionName, "bOnlyChunkedBuilds", out bOnlyChunkedBuilds))
		{
			bOnlyChunkedBuilds = false;
		}

		bool bOnlyNonChunkedBuilds = false;
		if (!PakRulesConfig.TryGetValue(SectionName, "bOnlyNonChunkedBuilds", out bOnlyNonChunkedBuilds))
		{
			bOnlyNonChunkedBuilds = false;
		}

		Logger.LogInformation("GetPakFileRules bChunkedBuild: {bChunkedBuild} bOnlyNonChunkedBuilds:{bOnlyNonChunkedBuilds}", bChunkedBuild, bOnlyNonChunkedBuilds);

		if (bChunkedBuild && bOnlyNonChunkedBuilds)
		{
			continue;
		}

		if (!bChunkedBuild && bOnlyChunkedBuilds)
		{
			continue;
		}

		string PlatformString;
		if (PakRulesConfig.TryGetValue(SectionName, "Platforms", out PlatformString))
		{
			string[] PlatformStrings = PlatformString.Split(new char[] { ',', ' ' }, StringSplitOptions.RemoveEmptyEntries);
			bool bMatches = false;

			// Check platform string
			foreach (string Platform in PlatformStrings)
			{
				if (SC.StageTargetPlatform.PlatformType.ToString().Equals(Platform, StringComparison.OrdinalIgnoreCase))
				{
					bMatches = true;
					break;
				}
				else if (SC.StageTargetPlatform.IniPlatformType.ToString().Equals(Platform, StringComparison.OrdinalIgnoreCase))
				{
					bMatches = true;
					break;
				}
			}

			if (!bMatches)
			{
				Logger.LogInformation("No matching platform for PakFileRules for Section {0} : {1}, {2}", SectionName, SC.StageTargetPlatform.PlatformType.ToString(), SC.StageTargetPlatform.IniPlatformType.ToString());
				continue;
			}
		}

		string TargetString;
		if (PakRulesConfig.TryGetValue(SectionName, "Targets", out TargetString))
		{
			string[] TargetStrings = TargetString.Split(new char[] { ',', ' ' }, StringSplitOptions.RemoveEmptyEntries);
			bool bMatches = false;

			// Check target string
			foreach (string Target in TargetStrings)
			{
				foreach (UnrealTargetConfiguration C in SC.StageTargetConfigurations)
				{
					if (C.ToString() == Target)
					{
						bMatches = true;
						break;
					}
				}
			}

			if (!bMatches)
			{
				continue;
			}
			else if (SC.StageTargetConfigurations.Count > 0 && !bWarnedAboutMultipleTargets)
			{
				bWarnedAboutMultipleTargets = true;
				Logger.LogInformation("Staging with more than one target, PakFileRules may apply too many rules!");
			}
		}

		PakFileRules PakRules = new PakFileRules();
		PakRules.Name = SectionName;
		PakRulesConfig.TryGetValue(SectionName, "bExcludeFromPaks", out PakRules.bExcludeFromPaks);
		PakRulesConfig.TryGetValue(SectionName, "bOverrideChunkManifest", out PakRules.bOverrideChunkManifest);
		PakRulesConfig.TryGetValue(SectionName, "bDisabled", out PakRules.bDisabled);
		string PakString;
		PakRulesConfig.TryGetValue(SectionName, "OverridePaks", out PakString);

		if (PakString != null && PakString.Length > 0)
		{
			PakRules.OverridePaks = PakString.Split(new char[] { ',', ' ' }, StringSplitOptions.RemoveEmptyEntries).ToList();
		}
		else
		{
			PakRules.OverridePaks = null;
		}

		if (PakRules.bExcludeFromPaks && PakRules.OverridePaks != null)
		{
			Logger.LogWarning("Error in PakFileRules {0}, set to exclude but also sets override!", PakRules.Name);
			continue;
		}
		else if (!PakRules.bExcludeFromPaks && PakRules.OverridePaks == null)
		{
			Logger.LogWarning("Error in PakFileRules {0}, set to include but did not specify paks!", PakRules.Name);
			continue;
		}

		IReadOnlyList<string> FilesEnumberable;
		if (PakRulesConfig.TryGetValues(SectionName, "Files", out FilesEnumberable))
		{
			// Only add if we have actual files, we can end up with none due to config overriding
			PakRules.Filter = new FileFilter();
			foreach (string FileFilter in FilesEnumberable)
			{
				Logger.LogInformation("Adding to PakFileRules for Section {0} : {1}", SectionName, FileFilter);
				PakRules.Filter.AddRule(FileFilter);
			}

			Logger.LogInformation("GetPakFileRules PakRules: {PakRules}", PakRules);

			RulesList.Add(PakRules);
		}
	}

	return RulesList;
}

在 ProjectName/Config/下创建DefaultPakFileRules.ini文件

; 这些规则按顺序应用,对于每个文件,第一个匹配的规则被采纳,后续规则不再评估。
; [SectionName]                       ; 匹配规则名称
; bOverrideChunkManifest=false        ; 如果为true,则允许覆盖来自cooker的分块清单分配。
; bExcludeFromPaks=false              ; 如果为true,则完全从.pak文件中排除此文件,不能与OverridePaks同时使用。
; OverridePaks="pakchunk1"            ; 如果设置,表示要将文件存放入哪个Pakchunk。
; Platforms="iOS,Android"             ; 如果设置,此规则仅适用于这些平台。
; Targets="Shipping,Test"             ; 如果设置,此规则仅适用于这些构建配置。
; bOnlyChunkedBuilds=true             ; 如果设置,此规则仅适用于分块构建。
; bOnlyNonChunkedBuilds=true          ; 如果设置,此规则仅适用于非分块构建。
; +Files=".../*FileMask*.*"           ; 应用于的文件列表,使用C# FileFilter类的文件掩码。
[ExcludeContentForMobile]
; 在移动平台上排除特定的大型纹理文件,此规则原先位于CopyBuildToStagingDirectory.cs中。
; 可以通过在游戏的DefaultPakFileRules.ini中使用相同的段落,并添加新的段落来增加规则。
; 要移除这条规则,可以使用!Files清除文件路径列表。
Platforms="Android,iOS,tvOS"                   ; 此规则仅适用于Android、iOS和tvOS平台。
bExcludeFromPaks=true                          ; 将这些文件完全排除在.pak文件之外。
bOverrideChunkManifest=true                    ; 允许覆盖从cooker获取的分块清单分配。
+Files=".../Engine/Content/EngineMaterials/DefaultBloomKernel.*"       ; 排除DefaultBloomKernel相关的所有文件。
+Files=".../Engine/Content/EngineMaterials/DefaultCalibrationColor.*"  ; 排除DefaultCalibrationColor相关的所有文件。
+Files=".../Engine/Content/EngineMaterials/DefaultCalibrationGrayscale.*" ; 排除DefaultCalibrationGrayscale相关的所有文件。
+Files=".../Engine/Content/EngineMaterials/PPM_DefaultCalibrationColor.*" ; 排除PPM_DefaultCalibrationColor相关的所有文件。
+Files=".../Engine/Content/EngineMaterials/PPM_DefaultCalibrationGrayscale.*" ; 排除PPM_DefaultCalibrationGrayscale相关的所有文件。其中

其中overridePaks 不能设置为已经存在的chunkID ,如果设置了 会在CreatePaksUsingChunkManifests中被判断返回掉,导致加入基础pak包
在这里插入图片描述
判断chunkdeinitions中是否有对应的chunkName,如果有就continue

CreatePaksUsingChunkManifests中处理了添加资源到chunk的逻辑,
读取Saved\TmpPackaging\Windows下的pakchunklist文件
在这里插入图片描述
通过PakfileRules添加的打包规则,会通过ApplyPakFileRules函数找到对应的chunk包添加进去。读取所有的chunk匹配规则,IsMatch函数确定文件是否符合筛选标准

使用projectLauncher进行打包

打基础包这样设置
在这里插入图片描述
打热更包这样设置
在这里插入图片描述
成功把lua脚本文件打入指定的chunk包啦
在这里插入图片描述
UE持续学习中,欢迎大佬指正错误之处。

个人踩坑记录,未经同意谢绝转载谢谢!

参考

https://zhuanlan.zhihu.com/p/523509674
https://zhuanlan.zhihu.com/p/401132377
https://zhuanlan.zhihu.com/p/682342893
https://link.zhihu.com/?target=https%3A//dev.epicgames.com/documentation/zh-cn/unreal-engine/how-to-create-a-patch-in-unreal-engine
https://link.zhihu.com/?target=https%3A//ue5wiki.com/wiki/61ac95b3/

  • 9
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值