UE4 LoadPackageAsync

虚幻4版本:4.15

先说说最关键的函数LoadPackageAsync  

加载路径 TEXT("/你的插件名字/xx“)

官网文档是[COREUOBJECT_API](API\Runtime\CoreUObject\UObject\COREUOBJECT_API_3)int32 LoadPackageAsync
(
    const FString & InName,
    FLoadPackageAsyncDelegate InCompletionDelegate,
    TAsyncLoadPriority InPackagePriority,
    EPackageFlags InPackageFlags,
    int32 InPIEInstanceID
)

如果是直接将地图打包进程序,这个函数还是很简单好用的

LoadPackageAsync(TEXT(/Game/xx), FLoadPackageAsyncDelegate::CreateLambda([&](const FName& PackageName, UPackage* LoadedPackage, EAsyncLoadingResult::Type Result) {}),0,PKG_ContainsMap);

但问题就在第一个参数上,如果是加载Dlc的形式,读取其他pak的话,这玩意填的路径简直逼死强迫症。需要的是TEXT("/你的插件名字/xx“)

(1)先获取Pak的路径

TArray<FString> GetAllFilesInDirector(const FString directory,const FString onlyFilesStartingWith,const FString extension){

    FString Directory1 =FPaths::GameDir()+ directory;

    TArray<FString> directoriesToSkip;

    IPlatformFile &PlatformFile =FPlatformFileManager::Get().GetPlatformFile();

    FLocalTimestampDirectoryVisitor Visitor(PlatformFile, directoriesToSkip, directoriesToSkip,false);

    PlatformFile.IterateDirectory(*Directory1, Visitor);

    TArray<FString> files;

    for (TMap<FString,FDateTime>::TIterator TimestampIt(Visitor.FileTimes); TimestampIt; ++TimestampIt)

  {

    const FString filePath = TimestampIt.Key();

    const FString fileName = FPaths::GetCleanFilename(filePath);

    const FString fileBaseName = FPaths::GetBaseFilename(filePath);

    bool shouldAddFile =true;

 

    if (!onlyFilesStartingWith.IsEmpty())

   {

     const FString left = fileName.Left(onlyFilesStartingWith.Len());

     if (!(fileName.Left(onlyFilesStartingWith.Len()).Equals(onlyFilesStartingWith)))

       shouldAddFile = false;

    }

 

    if (!extension.IsEmpty())

      if (!(FPaths::GetExtension(fileName,false).Equals(extension, ESearchCase::IgnoreCase)))

         shouldAddFile = false;


    if (shouldAddFile)

        files.Add(filePath);

   }

return files;

}

使用方法:

TArray<FString> PakFiles;

PakFiles= MyToolsHelper::GetAllFilesInDirector("Content/Paks/","","pak");

(2)遍历Pak中的文件找到要加载的地图的全路径

先获取Pak中的所有文件

TArray<FString> getAllFilesByPak(const FString pakPath){

IPlatformFile& PlatformFile = FPlatformFileManager::Get().GetPlatformFile();

FPakPlatformFile* PakPlatformFile = new FPakPlatformFile();

PakPlatformFile->Initialize(&PlatformFile,TEXT(""));

FPlatformFileManager::Get().SetPlatformFile(*PakPlatformFile);

 

FPakFile PakFile(&*PakPlatformFile, *pakPath, false);

if (!PakFile.IsValid())return TArray<FString>();

TArray<FString> FileList;

PakFile.SetMountPoint(*FPaths::EngineContentDir());

PakFile.FindFilesAtPath(FileList, *PakFile.GetMountPoint(),true,false,true);

return FileList;

}

使用方法:getAllFilesByPak(pakPath);

遍历文件列表获取想要打开的地图全路径

auto res=Files.FindByPredicate([&](FString str) {

         auto FileName =FPackageName::GetShortName(str);

         if (FileName.EndsWith(FPackageName::GetMapPackageExtension())){

              FString left, right;

              FileName.Split(TEXT("."), &left, &right);

              if (left.Equals(name))return true;

          }

          return false;

});

if (res)fullPath= *res

前面的结合起来就是

TArray<FString> PakFiles;

       PakFiles= getAllPaks();

       FString fullPath;

       for (FString pakPath : PakFiles) {

         auto Files = getAllFilesByPak(pakPath);

         auto res=Files.FindByPredicate([&](FString str) {

             auto FileName =FPackageName::GetShortName(str);

             if (FileName.EndsWith(FPackageName::GetMapPackageExtension())){

                 FString left, right;

                 FileName.Split(TEXT("."), &left, &right);

                 if (left.Equals(name))return true;

             }

         return false;});

        if (res) {

         fullPath= *res;

         break;

         }

}

 

如果一切没有问题,那你获得的路径应该是类似这种

"../../../Engine/Content/你的项目名字/Plugins/你的DLC插件名字/Content/xx.umap"  

如果xx.umap在插件内容目录的a/b/c/xx.umap

"../../../Engine/Content/你的项目名字/Plugins/你的DLC插件名字/Content/a/b/c/xx.umap"  

 

(3)对路径字符串解析获取出/DLC名字/+地图在DLCContent中的存取路径

FString left, right,DLCName,contentPath;

先获取DLC名字

        fullPath.Split(TEXT("Plugins"),&left, &right);

right.Split(TEXT("Content/"), &DLCName, &left);

再获取地图在插件内容目录中的路径

left.Split(name, &contentPath, &FString());

最后再合并

auto loadPath = DLCName+ contentPath+ name;

(4)LoadPackageAsync加载资源,并在回调方法中调用加载关卡的命令

这里就简单多了,只要能找到路径其他都不是问题

LoadPackageAsync(loadPath,FLoadPackageAsyncDelegate::CreateLambda([&,name](const FName&PackageName,UPackage*LoadedPackage, EAsyncLoadingResult::Type Result) {

GEngine->AddOnScreenDebugMessage(-1, 15.0f, FColor::Yellow,name);

if(Result== EAsyncLoadingResult::Failed)

 

GEngine->AddOnScreenDebugMessage(-1, 15.0f, FColor::Yellow,TEXT("Failed"));

else if(Result == EAsyncLoadingResult::Succeeded)

GEngine->AddOnScreenDebugMessage(-1, 15.0f, FColor::Yellow,TEXT("Succeeded"));

else

GEngine->AddOnScreenDebugMessage(-1, 15.0f, FColor::Yellow,TEXT("cancel"));

UGameplayStatics::OpenLevel(GetWorld(),*name);

}), 0,PKG_ContainsMap);

 

然后将上面的东西都写在一个类当中,当然最好是继承GameInstance这种

猜你喜欢

转载自blog.csdn.net/or7rccl/article/details/80213389
UE4