zoukankan      html  css  js  c++  java
  • Unreal: Dynamic load map from Pak file

    Unreal: Dynamic load map from Pak file

    目标:在程序运行时加载自定义 Pak 文件,并打开指定关卡,显示其中的完整 map 内容

    Unreal 的 Pak 文件内包括了物体,材质,blueprint,map等等。Level 以 map 的形式保存。

    Firsr of all, Pak 相关的调试需要 Package Project 执行,不能在 Editor 里面直接 Launch,否则 FCoreDelegates::MountPak IsBound 为 false , 则无法执行后续操作。

    Code

    在 GameMode 的 InitGame() 内调用如下代码。

    void MyMainClass::MyMainClass::Exe(UWorld *world) {
        UE_LOG(LogTemp, Warning, TEXT("Init Main class"));
        if (FCoreDelegates::MountPak.IsBound())
        {
            UE_LOG(LogTemp, Warning, TEXT("LoadPakDelegate(): OnMountPak.IsBound()"));
            FString pakPath = TEXT("../../../MyProject3/Content/Paks/MyProject1-MacNoEditor.pak");
            IPakFile *pakFile = FCoreDelegates::MountPak.Execute(pakPath, 4);
          if (pakFile)
          {
            const auto& mountPoint = pakFile->PakGetMountPoint();
                  UE_LOG(LogTemp, Warning, TEXT("LoadPakDelegate(): MountPoint %s"), *mountPoint);
            FString pakContentPath = mountPoint + "MyProject1/Content/";
          // FPackageName::RegisterMountPoint("/Game/", "../../../MyProject1/Content/");
          FPackageName::RegisterMountPoint("/Game/", pakContentPath);
    
          UGameplayStatics::OpenLevel(world, FName(TEXT("Map2")) );
          }
        }
        else
        {
            UE_LOG(LogTemp, Warning, TEXT("LoadPakDelegate(): OnMountPak.IsBound() Falied"));
        }
    }
    

    RegisterMountPoint 的分析

    static void  RegisterMountPoint
    (
        const FString  & RootPath,
        const FString  & ContentPath
    )
    
    

    This will insert a mount point at the head of the search chain (so it can overlap an existing mount point and win).

    参数解释:

    RootPath: Logical Root Path.

    ContentPath: Content Path on disk.

    Logical Path 是程序运行时会去找的 path 并非实际路径,根据反复尝试,只有在这个参数写成 “/Game/” 的时候才能正确加载到所有资源,若随意命名可能只能加载到 map 资源,连 map_builtdata 都找不到。会有如下报错:
    LogStreaming: Error: Couldn't find file for package /Game/StarterContent/Maps/Map2_BuiltData requested by async loading code. NameToLoad: /Game/StarterContent/Maps/Map2_BuiltData

    我的猜测是当前运行的程序的默认加载路径是 Game 所以这样写可以成功,应该也有方法自定义加载的路径,但是我暂时不知道。

    Content Path 是指需要 mount 到前面这个目录的内容的父路径,这个路径取决于加载的Pak 的当前挂载点和 Pak 内部的文件路径。

    通过 PakGetMountPoint() 函数得到挂载点为 "../../../"
    而且 Pak 内部文件如下

    MyProject1/Content/StarterContent/Blueprints/...
    MyProject1/Content/StarterContent/Maps/...
    MyProject1/Content/StarterContent/Materials/...
    MyProject1/Content/StarterContent/Shapes/...
    ...
    

    故最终路径为 “../../../MyProject1/Content/”

    Missing shader resource

    成功加载 map 但是模型材质和 shader 丢失,log 如下:

    [UE4] [2021.05.17-03.57.53:734][  0]LogShaders: Error: Missing shader resource for hash '589973CAE03D7F0ECFEC6B825B774136FF9FCB9D' for shader platform 16 in the shader library
    LogMaterial: Error: Tried to access an uncooked shader map ID in a cooked application
    [UE4] [2021.05.17-08.02.25:186][  0]LogMaterial: Can't compile BasicShapeMaterial with cooked content, will use default material instead
    

    这个问题原因是在要加载 Pak 的工程设置里面启用了 Share Material Shader Code,启用这个选项会 “Save shader only once” 这样的优化选项导致了外部的 shader 无法被找到。
    在工程中关闭此开关即可。

    Ref:

    https://answers.unrealengine.com/questions/363767/how-to-load-a-map-from-a-dynamic-level.html 参见 TestyRabbit May 03 '18 at 4:07 PM 的评论

    sample code: https://pastebin.com/ZWAPtynK

    https://answers.unrealengine.com/questions/258386/loading-map-from-pak-at-runtime.html top 回答

    https://answers.unrealengine.com/questions/963414/view.html

  • 相关阅读:
    下载程序的疑问
    Beaglebone环境建立:电源适配器供电+网线ssh
    Android百分比布局支持库介绍——com.android.support:percent
    android应用中去掉标题栏的方法
    自己写的进度条
    返回图片指定点的RGB值
    修改指定图片的分辨率
    跨域访问的问题和解决过程
    C#取硬盘、CPU、主板、网卡的序号 ManagementObjectSearcher
    Sql Server字符串函数
  • 原文地址:https://www.cnblogs.com/psklf/p/14778289.html
Copyright © 2011-2022 走看看