参考知乎UE5 Pak学习与应用(一)运行时导入模型 - 知乎
使用的版本为UE5.1 使用插件为HorPatcher和EasyFile Dialog
HotPatcher:UE资源热更打包工具HotPatcher | 循迹研究室 ,Github地址为:GitHub - hxhb/HotPatcher: Unreal Engine hot update manage and package plugin.
EasyFile Diaglog插件地址为:Easy File Dialog in Code Plugins - UE Marketplace
首先修改项目设置
创建一个GameModeBase.h的游戏模式蓝图
在世界选项中修改游戏模式
在UE中启用插件
这里两个插件我都是放在项目目录下
在需要烘培的资源这里右键
这里填写VersionID(PAK包名),PAK Target Platforms(PAK包目标平台)
填好后点击右下角GeneratePatch即可
进入Windows就可以复制PAK包
然后是进入项目的Build.cs文件将PakFile,EasyFileDialog和HotPatcherRuntime加入模块
然后写代码,具体思路是读取到PAK包内的资源,然后把资源转为指定的类,再调用类到场景内
// Fill out your copyright notice in the Description page of Project Settings. #include "PAKLoadGameModeBase.h" #include "IPlatformFilePak.h" #include "Engine/StaticMeshActor.h" #include "EFDCore.h" #include "FlibPakHelper.h" void APAKLoadGameModeBase::ImportModePak() { TArray<FString> OutFilenames; //这里是使用Windows的文件资源选择器 EFDCore::OpenFileDialogCore(TEXT("Choose a .pak file"), FPaths::ProjectDir(), "", ".pak", EEasyFileDialogFlags::Single, OutFilenames); UE_LOG(LogTemp, Warning, TEXT("OpenFileDialogCore!")); if (OutFilenames.Num() > 1) { UE_LOG(LogTemp, Warning, TEXT("请一次选择一个文件!")); return; } else if (OutFilenames.Num() == 1) { //这一段是处理路径 FString PakFileFullPath = OutFilenames[0]; FPakPlatformFile* PakPlatformFile = (FPakPlatformFile*)FPlatformFileManager::Get().GetPlatformFile(FPakPlatformFile::GetTypeName()); if (!PakPlatformFile) { UE_LOG(LogTemp, Log, TEXT("GetPlatformFile(TEXT(\"PakFile\") is NULL")); return; } PakFileFullPath = FPaths::ConvertRelativePathToFull(PakFileFullPath); TRefCountPtr<FPakFile> TmpPak = new FPakFile(PakPlatformFile, *PakFileFullPath, false); FString MountPoint = TmpPak->GetMountPoint(); int32 PosContent = MountPoint.Find("../../../", ESearchCase::Type::IgnoreCase, ESearchDir::FromEnd); FString NewMountPoint = MountPoint.LeftChop(PosContent); if (FPaths::FileExists(PakFileFullPath) && FPaths::GetExtension(PakFileFullPath) == TEXT("pak")) { // 注意 ProjectSetting 中的 UseIoStore需要取消勾选,否则挂载不上 bool MountRet = UFlibPakHelper::MountPak(*PakFileFullPath, 0, *MountPoint); if (MountRet) { TArray<FString> FoundFileNames; //将路径挂载在TmpPak下 TmpPak->FindPrunedFilesAtPath(FoundFileNames, *MountPoint, true, false, true); if (FoundFileNames.Num() > 0) { for (FString& FileName : FoundFileNames) { //检查PAK包内的.uasset文件 if (FileName.EndsWith(".uasset")) { FString NewFileName = FileName; NewFileName.RemoveFromEnd(TEXT(".uasset")); int32 Pos = NewFileName.Find("/Content/"); NewFileName = NewFileName.RightChop(Pos + 8); NewFileName = "/Game" + NewFileName; //加载资源 UObject* LoadedObj = StaticLoadObject(UObject::StaticClass(), NULL, *NewFileName); if (LoadedObj) { UE_LOG(LogTemp, Warning, TEXT("加载pak文件成功")); UStaticMesh* SM = Cast<UStaticMesh>(LoadedObj); if (SM) { AStaticMeshActor* SMA = GetWorld()->SpawnActor<AStaticMeshActor>(); if (SMA) { //设置StaticMeshActor的方式为移动,如果是固定则可能在SpawnActor的时候生成失败 SMA->SetMobility(EComponentMobility::Movable); SMA->GetStaticMeshComponent()->SetStaticMesh(SM); } //设置生成坐标 SMA->SetActorLocation(FVector(200.f, 0.f, 100.f)); } } else { UE_LOG(LogTemp, Warning, TEXT("load pak file failed")); } } } } } } } }