UE4 Pak打包、挂载、加载

首先,必须得明确的一点就是如果想要加载Pak内资源,那么这些资源必须是经过Cook的。如果打包的是未Cook的资源,那么即使Pak挂载成功,也不可能会成功加载Pak内资源。

不知道怎么生成Cook资源,可以看我前一篇 ​​​​​​UE4 Cook指定平台资源_来梦学长i的博客-CSDN博客

打包Pak

首先,将引擎目录下"Engine\Binaries\Win64"添加到系统环境变量中

方式一:使用命令行方式打包

打包Pak的命令行格式

UnrealPak “存储Pak的路径+Pak包名” -create="Cook好的资源的路径"

打开CMD键入打包命令,执行打包Pak

示例一:打包整个Content文件

UnrealPak "E:\ProjectName\Pak\ContentPak.pak" -create="E:\ProjectName\Saved\Cooked\Content"

示例二:打包单个指定文件

UnrealPak "E:\ProjectName\Pak\SiglePak.pak" -create="E:\ProjectName\Saved\Cooked\Content\FileName\FileName.uasset"

方式二:使用批处理方式打包

@ECHO OFF
ECHO ---------------------------------------------------------------
ECHO		UnrealPak Strart Create Pak
ECHO ---------------------------------------------------------------

set PakFilename="E:\AndroidVR\Pak\ContentPak.pak"
set CookedFileName="E:\AndroidVR\Saved\Cooked\Newfile"
set UnrealPak="E:\UE4.26\Engine\Binaries\Win64\UnrealPak.exe"
CALL %UnrealPak% %PakFilename%  -create=%CookedFileName%


ECHO ---------------------------------------------------------------
ECHO		UnrealPak Finished
ECHO ---------------------------------------------------------------
PAUSE

  打包完成,即可在你自己指定的目录下找到打包好的Pak文件

挂载Pak

如果手动将Pak放在以下这些项目路径中,引擎将会自动加载Pak

  • [ProjectName]/Content/Paks
  • [ProjectName]/Saved/Paks
  • Engine/Content/Paks

也可以使用以下方法,手动挂载Pak

挂载Pak的功能需要C++代码实现,项目Build.cs中加入"PakFile"模块

包含必要头文件

#include "HAL/PlatformFilemanager.h"
#include "IPlatformFilePak.h"

创建函数,用于获取平台文件

FPakPlatformFile* FSimpleHotPakModule::GetPakPlatformFile()
{
	if (!PakPlatformFile)
	{
		if (IPlatformFile* InPlatformFile = FPlatformFileManager::Get().FindPlatformFile(TEXT("PakFile")))
		{
			PakPlatformFile = static_cast<FPakPlatformFile*>(InPlatformFile);
		}
		else
		{
			PakPlatformFile = new FPakPlatformFile();
			if (PakPlatformFile->Initialize(&FPlatformFileManager::Get().GetPlatformFile(), TEXT("")))
			{
				FPlatformFileManager::Get().SetPlatformFile(*PakPlatformFile);
			}
		}
	}

	return PakPlatformFile;
}

创建函数,用于判断是否已经挂载指定Pak,防止重复挂载

@PakFilename       Pak包名

bool USimpleHotPakBPLibrary::IsMounted(const FString& PakFilename)
{
	if (FPakPlatformFile* InPakFile = GetPakPlatformFile())
	{
		TArray<FString> PakFilenames;
		//获取已经挂载的Pak数组容器
		InPakFile->GetMountedPakFilenames(PakFilenames);
		//判断其中是否已经包含Pak
		return PakFilenames.Contains(PakFilename);
	}
	return false;
}

 创建函数,用于挂载Pak

@PakFilename       Pak包名
@PakOrder          Pak加载优先级
@MountPoint        Pak挂载到哪个路径

bool AHotUpdateTestCharacter::MountPak(const FString& PakFilename, int32 PakOrder, const FString& MountPoint)
{
	if (FPakPlatformFile *InPakFile = GetPakPlatformFile())
	{
		if (!IsMounted(PakFilename))
		{
            //返回挂载结果
			return InPakFile->Mount(*PakFilename, PakOrder, *MountPoint);
		}
	}
	return false;
}

创建函数,用于卸载Pak

@PakFilename       Pak包名

bool AHotUpdateTestCharacter::UnmountPak(const FString& PakFilename)
{
	if (FPakPlatformFile* InPakFile = GetPakPlatformFile())
	{
		return InPakFile->Unmount(*PakFilename);
	}

	return false;
}

方法都准备好了,开始挂载Pak

值得说明的是,MountPoint路径是你所打包的Cook资源的相对路径

例如打包了一个"ProjectName/Saved/Cooked/Content/Asseset"路径下的资源,那么这个资源的挂载点则是"ProjectName/Content/Asseset"

//Pak文件路径
FString PakFileName = FPaths::ProjectDir() / TEXT("Pak/Asset.pak");
//Pak挂载点
FString PakMountPoint = FPaths::ProjectContentDir() / TEXT("Asset/");

if(MountPak(*PakFileName,3,*PakMountPoint))
{
    
}

这样就已经将Pak挂载到引擎中了,接下来则是加载Pak中的资源

资源加载

动态加载资源

//Pak文件路径
FString PakFileName = FPaths::ProjectDir() / TEXT("Pak/Asset.pak");
//Pak挂载点
FString PakMountPoint = FPaths::ProjectContentDir() / TEXT("Asset/");

if(MountPak(*PakFileName,3,*PakMountPoint))
{
    FString AssetPath = "'Blueprint'/Gmae/Asseset/AssetName.AssetName_C'";
    if(AActor *TheActor = Cast<AActor>(StaticLoadObject(UObject::StaticClass(),nullptr,*AssetPath)))
    {
        GetWorld()->SpawnActor(TheActor,FVector(),FRotator());
    }
}

异步加载资源

//Pak文件路径
	FString PakFileName = FPaths::ProjectDir() / TEXT("Pak/Asset.pak");
	//Pak挂载点
	FString PakMountPoint = FPaths::ProjectContentDir() / TEXT("Asset/");

	if(MountPak(*PakFileName,3,*PakMountPoint))
	{
		if (FPakPlatformFile*InPakPlatformFile = GetPakPlatformFile())
		{
			FPakFile*InPakFile = new FPakFile(InPakPlatformFile,*PakFileName,false);
			
			TArray<FSoftObjectPath> AllReourcePath;
			TArray<FString> Files;
			InPakFile->FindFilesAtPath(Files,*InPakFile->GetMountPoint(),true,false,true);
			for (auto &InPak : Files)
			{
				AllReourcePath.AddUnique(InPak);
			}
			UAssetManager::GetStreamableManager().RequestAsyncLoad(AllReourcePath,FStreamableDelegate::CreateLambda([&]()
			{
				FString FileName = "'Blueprint'/Gmae/Asseset/AssesetName.AssesetName'";
				AActor*TheActor = FindObject<AActor>(nullptr,*FileName);
			}));
		}
	}

猜你喜欢

转载自blog.csdn.net/weixin_45500363/article/details/128317240
今日推荐