UE5分包挂载dlc
1、将需要分包挂载的资产整理到单独的插件下(方便好管理)
2、用 Primary Asset Label 标记 DLC 资产
1)开启分块功能:打开 Project Settings → Packaging,勾选 Use Pak File 和 Generate Chunks

2)创建 Primary Asset Label:在你的 DLC 插件的 Content 目录下,右键 → Miscellaneous → Data Asset → 选择 PrimaryAssetLabel 作为基类

3)配置 Label:双击打开这个新创建的 Data Asset,按以下设置

4)有时打包后不能打出分块数据,按下面顺序依次尝试
a)PrimaryAssetLabel 里手动引用一个插件的数据,让系统找到数据

b)由于地图关卡地图(Map)本身也是一种 PrimaryAsset,它有自己的 ChunkID,会覆盖 PrimaryAssetLabel 的分配,必须通过 ini 配置来指定
DefaultGame.ini里增加类似如下代码
[/Script/Engine.AssetManagerSettings]
+PrimaryAssetRules=(PrimaryAssetId="Map:/TVRCharactor/Maps/testMap1",Rules=(Priority=-1,ChunkId=1001,CookRule=AlwaysCook))
c)检查PrimaryAssetLabel 是否被 AssetManager 扫描到

在此处加上插件目录
3、正常打包项目
直接像平时打包基础游戏一样,用 RunUAT 或 Project Launcher 进行打包即可。打包结束后,可以看见主包和分包:

4、运行时加载
分块打包生成的 pakchunk1001 默认不会被游戏自动加载。你需要在游戏启动时,用代码主动去挂载它。
官方提供的 PakDemo 示例项目展示了完整的运行时加载方案,核心逻辑是调用
主要代码在BFL_Pak中
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once #include "CoreMinimal.h" #include "Kismet/BlueprintFunctionLibrary.h" #include "BFL_Pak.generated.h" UCLASS() class TVRSIMDRILLLITE_API UBFL_Pak : public UBlueprintFunctionLibrary { GENERATED_BODY() public: UFUNCTION(BlueprintCallable, Category = "PAK") static void MountAndRegisterPak(FString PakFilePath,bool& bIsMountSuccessful); UFUNCTION(BlueprintCallable, Category = "PAK") static bool MountPakFile(const FString& PakFilePath, const FString& PakMountPoint); UFUNCTION(BlueprintCallable, Category = "PAK") static bool UnmountPakFile(const FString& PakFilePath); UFUNCTION(BlueprintCallable, Category = "PAK") static void RegisterMountPoint(const FString& RootPath, const FString& ContentPath); UFUNCTION(BlueprintCallable, Category = "PAK") static void UnRegisterMountPoint(const FString& RootPath, const FString& ContentPath); UFUNCTION(BlueprintCallable,BlueprintPure, Category = "PAK") static FString const GetPakMountPoint(const FString& PakFilePath); UFUNCTION(BlueprintCallable,BlueprintPure, Category = "PAK") static TArray<FString> GetPakContent(const FString& PakFilePath, bool bOnlyCooked = true); UFUNCTION(BlueprintCallable,BlueprintPure, Category = "PAK") static FString GetPakMountContentPath(const FString& PakFilePath); UFUNCTION(BlueprintCallable, BlueprintPure, Category = "PAK") static UClass* LoadPakObjClassReference(FString PakContentPath); UFUNCTION(BlueprintCallable, BlueprintPure, Category = "PAK") static UClass* LoadPakFileClass(const FString& FileName); UFUNCTION(BlueprintCallable, BlueprintPure, Category = "PAK") static FString Conv_PakContentPathToReferenceString(const FString PakContentPath, const FString PakMountPath); }; // Fill out your copyright notice in the Description page of Project Settings. #include "BFL_Pak.h" #include "IPlatformFilePak.h" bool UBFL_Pak::MountPakFile(const FString& PakFilePath, const FString& PakMountPoint) { int32 PakOrder = 0; bool bIsMounted = false; //Check to see if running in editor #if WITH_EDITOR return bIsMounted; #endif FString InputPath = PakFilePath; FPaths::MakePlatformFilename(InputPath); FPakPlatformFile* PakFileMgr = (FPakPlatformFile*)(FPlatformFileManager::Get().FindPlatformFile(TEXT("PakFile"))); if (PakFileMgr == nullptr) { UE_LOG(LogTemp, Warning, TEXT("Unable to get PakPlatformFile for pak file (mount): %s"), *(PakFilePath)); return false; } if (!PakMountPoint.IsEmpty()) { bIsMounted = PakFileMgr->Mount(*InputPath, PakOrder, *PakMountPoint); } else { bIsMounted = PakFileMgr->Mount(*InputPath, PakOrder); } return bIsMounted; } bool UBFL_Pak::UnmountPakFile(const FString& PakFilePath) { FPakPlatformFile* PakFileMgr = (FPakPlatformFile*)(FPlatformFileManager::Get().FindPlatformFile(TEXT("PakFile"))); if (PakFileMgr == nullptr) { UE_LOG(LogTemp, Warning, TEXT("Unable to get PakPlatformFile for pak file (Unmount): %s"), *(PakFilePath)); return false; } return PakFileMgr->Unmount(*PakFilePath); } void UBFL_Pak::RegisterMountPoint(const FString& RootPath, const FString& ContentPath) { FPackageName::RegisterMountPoint(RootPath, ContentPath); } void UBFL_Pak::UnRegisterMountPoint(const FString& RootPath, const FString& ContentPath) { FPackageName::UnRegisterMountPoint(RootPath, ContentPath); } FString const UBFL_Pak::GetPakMountPoint(const FString& PakFilePath) { FPakFile* Pak = nullptr; TRefCountPtr<FPakFile> PakFile = new FPakFile(FPlatformFileManager::Get().FindPlatformFile(TEXT("PakFile")), *PakFilePath, false); Pak = PakFile.GetReference(); if (Pak->IsValid()) { return Pak->GetMountPoint(); } return FString(); } TArray<FString> UBFL_Pak::GetPakContent(const FString& PakFilePath, bool bOnlyCooked /*= true*/) { FPakFile* Pak = nullptr; TRefCountPtr<FPakFile> PakFile = new FPakFile(FPlatformFileManager::Get().FindPlatformFile(TEXT("PakFile")), *PakFilePath, false); Pak = PakFile.GetReference(); TArray<FString> PakContent; if (Pak->IsValid()) { FString ContentPath, PakAppendPath; FString MountPoint = GetPakMountPoint(PakFilePath); MountPoint.Split("/Content/", &ContentPath, &PakAppendPath); TArray<FPakFile::FFilenameIterator> Records; for (FPakFile::FFilenameIterator It(*Pak, false); It; ++It) { Records.Add(It); } for (auto& It : Records) { if (bOnlyCooked) { if (FPaths::GetExtension(It.Filename()) == TEXT("uasset")) { PakContent.Add(FString::Printf(TEXT("%s%s"), *PakAppendPath, *It.Filename())); } } else { PakContent.Add(FString::Printf(TEXT("%s%s"), *PakAppendPath, *It.Filename())); } } } return PakContent; } FString UBFL_Pak::GetPakMountContentPath(const FString& PakFilePath) { FString ContentPath, RightStr; bool bIsContent; FString MountPoint = GetPakMountPoint(PakFilePath); bIsContent = MountPoint.Split("/Content/", &ContentPath, &RightStr); if (bIsContent) { return FString::Printf(TEXT("%s/Content/"), *ContentPath); } // Check Pak Content for /Content/ Path else { TArray<FString> Content = GetPakContent(PakFilePath); if (Content.Num() > 0) { FString FullPath = FString::Printf(TEXT("%s%s"), *MountPoint, *Content[0]); bIsContent = FullPath.Split("/Content/", &ContentPath, &RightStr); if (bIsContent) { return FString::Printf(TEXT("%s/Content/"), *ContentPath); } } } //Failed to Find Content return FString(""); } void UBFL_Pak::MountAndRegisterPak(FString PakFilePath, bool& bIsMountSuccessful) { FString PakRootPath = "/Game/"; if (!PakFilePath.IsEmpty()) { if (MountPakFile(PakFilePath, FString())) { bIsMountSuccessful = true; const FString MountPoint = GetPakMountContentPath(PakFilePath); RegisterMountPoint(PakRootPath, MountPoint); } } } UClass* UBFL_Pak::LoadPakObjClassReference(FString PakContentPath) { FString PakRootPath = "/Game/"; const FString FileName = Conv_PakContentPathToReferenceString(PakContentPath, PakRootPath); return LoadPakFileClass(FileName); } UClass* UBFL_Pak::LoadPakFileClass(const FString& FileName) { const FString Name = FileName + TEXT(".") + FPackageName::GetShortName(FileName) + TEXT("_C"); return StaticLoadClass(UObject::StaticClass(), nullptr, *Name); } FString UBFL_Pak::Conv_PakContentPathToReferenceString(const FString PakContentPath, const FString PakMountPath) { return FString::Printf(TEXT("%s%s.%s"), *PakMountPath, *FPaths::GetBaseFilename(PakContentPath, false), *FPaths::GetBaseFilename(PakContentPath, true)); }
在蓝图中执行挂载即可


浙公网安备 33010602011771号