ue4-异步加载资源

版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/yangxuan0261/article/details/54408683
  • 异步加载资源

  • ue中的异步加载分为两种模式,具体源码在 AsyncLoading.cpp

    1. 主线程分帧加载。
    2. 多线程加载。
  • 可以通过接口判断当前的异步模式是那种模式。

    const bool bIsMultithreaded = FAsyncLoadingThread::IsMultithreaded();

思路

  1. 一个FVCharPartInfo物件结构体,里面id和TAssetPtr对mesh资源的的指针。
  2. 一个UItemInfoDatabase物件数据库,里面有一个物件列表TArray
  3. 一个全局单例类USolusDataSingleton,里面有个资源加载器struct FStreamableManager* AssetLoader和物件数据库class UItemInfoDatabase* ItemDatabase
  4. 使用加载器异步请求加载物件数据库里的物件列表
    有个不好的地方就是,绑定加载完的回调指针,不能在获取对应的加载的对象

实现

  1. 物件和数据库都在 ItemInfoDatabase.h 中(++ps++:如果修改了 FVCharPartInfo,记得要重新启动一下编辑器,否则这个结构体在编辑器中没有变化)

    • ItemInfoDatabase.h

      
      #pragma once
      
      
      #include "Engine/DataAsset.h"
      
      
      #include "ItemInfoDatabase.generated.h"
      
      
      USTRUCT()
      struct FVCharPartInfo
      {
          GENERATED_USTRUCT_BODY()
          UPROPERTY(EditAnywhere, Category = "DATA")
              int32 MeshID;
      
          UPROPERTY(EditAnywhere, Category = "DATA")
              TAssetPtr<USkeletalMesh> MeshResource;
      
          FVCharPartInfo()
          {
              MeshID = 0;
              MeshResource = FStringAssetReference("");
          }
      };
      
      //Holds a dynamic collection of character parts
      UCLASS(BlueprintType)
      class UItemInfoDatabase : public UDataAsset
      {
          GENERATED_UCLASS_BODY()
          UPROPERTY(EditAnywhere, Category = "Model List") //Exposes the array as editable on editor
          TArray<FVCharPartInfo> MeshList;
      
      public:
          UItemInfoDatabase();
      };
    • ItemInfoDatabase.cpp

      ItemInfoDatabase.cpp
      
      #include "MySlate.h"
      
      
      #include "ItemInfoDatabase.h"
      
      
      UItemInfoDatabase::UItemInfoDatabase(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer)
      {
      }
  2. 在Editor中建个UItemInfoDatabase蓝图类

    • 在编辑器中把资源引用添加进去,下面的单例类会直接加载这个UitemInfoDatabase载蓝图类
      这里写图片描述

    • 添加资源的引用
      这里写图片描述

  3. 全局单例类,初始化时把数据库加进去

    • SolusDataSingleton.h

      
      #pragma once
      
      
      #include "SolusDataSingleton.generated.h"
      
      
      struct FStreamableManager;
      class UItemInfoDatabase;
      
      UCLASS(Blueprintable, BlueprintType)
      class USolusDataSingleton : public UObject
      {
          GENERATED_BODY()
      public:
          USolusDataSingleton(const FObjectInitializer& ObjectInitializer);
          virtual ~USolusDataSingleton();
      
          static USolusDataSingleton* Get();  // Get method to access this object
          struct FStreamableManager* AssetLoader;     // Your asset loader
          class UItemInfoDatabase* ItemDatabase;      
      };
    • SolusDataSingleton.cpp

      
      #include "MySlate.h"
      
      
      #include "SolusDataSingleton.h"
      
      
      
      #include "Engine.h"
      
      
      #include "Engine/StreamableManager.h"
      
      
      #include "Singleton/SolusDataSingleton.h"
      
      
      #include "Singleton/ItemInfoDatabase.h"
      
      
      USolusDataSingleton::USolusDataSingleton(const FObjectInitializer& ObjectInitializer)
          : Super(ObjectInitializer)
      {
          AssetLoader = new FStreamableManager();
      
          //加载itemDataBase蓝图类
          UObject* obj = AssetLoader->SynchronousLoad(FStringAssetReference(TEXT("/Game/TopDownCPP/MeshItems/MeshDateBaseBP")));
          ItemDatabase = Cast<UItemInfoDatabase>(obj);
      }
      
      USolusDataSingleton::~USolusDataSingleton()
      {
          if (AssetLoader)
              delete AssetLoader;
      }
      
      USolusDataSingleton* USolusDataSingleton::Get()
      {
          USolusDataSingleton* DataInstance = Cast<USolusDataSingleton>(GEngine->GameSingleton); //这里指定配置文件中指定的单例类
          if (!DataInstance)
              return nullptr;
          else
              return DataInstance;
      }
  4. 在BpLib中起个方法测试异步加载

    //h
    UFUNCTION(BlueprintCallable, Category = "Async Load")
        static UObject* TestAsyncLoad(AMyChar* _myChar);
    //cpp
    bool UMyBpFuncLib::TestAsyncLoad(AMyChar* _myChar)
    {
        if (!_myChar)
            return false;
    
        FStreamableManager* BaseLoader = USolusDataSingleton::Get()->AssetLoader;
        UItemInfoDatabase* _database = USolusDataSingleton::Get()->ItemDatabase;
    
        if (!BaseLoader || !_database)
            return false;
    
        TArray<FStringAssetReference> ObjToLoad;
        for (int32 i = 0; i < _database->MeshList.Num(); ++i)
        {
            ObjToLoad.AddUnique(_database->MeshList[i].MeshResource.ToStringReference());
        }
        //请求异步加载
        BaseLoader->RequestAsyncLoad(ObjToLoad, FStreamableDelegate::CreateUObject(_myChar, &AMyChar::TestAsyncLoad));
        return true;
    }
    
    //回调方法
    void AMyChar::TestAsyncLoad()
    {
        FString str = FString::Printf(TEXT("--- AMyChar::TestAsyncLoad callback"));
        GEngine->AddOnScreenDebugMessage(0, 5.0f, FColor::Red, str);
    }
  5. 蓝图调用测试方法
    这里写图片描述

  6. 结果
    这里写图片描述


参考资料

展开阅读全文

没有更多推荐了,返回首页