1.创建一个C++资源库ItemInfoDatabase.h
.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<AActor> 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(); };
.cpp
// Fill out your copyright notice in the Description page of Project Settings. #include "TTTTT.h" #include "ItemInfoDatabase.h" UItemInfoDatabase::UItemInfoDatabase(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer) { }
2.以这个C++类创建一个数据资源,并写入数据
3.创建全局单例类MyGameSingleton.h .h
// Fill out your copyright notice in the Description page of Project Settings. #pragma once #include "UObject/NoExportTypes.h" #include "MyGameSingleton.generated.h" /** * */ //struct FStreamableManager; //class UItemInfoDatabase; UCLASS(Blueprintable, BlueprintType) class TTTTT_API UMyGameSingleton : public UObject { GENERATED_BODY() public: UMyGameSingleton(const FObjectInitializer& ObjectInitializer); virtual ~UMyGameSingleton(); static UMyGameSingleton* Get(); // Get method to access this object struct FStreamableManager* AssetLoader; // Your asset loader class UItemInfoDatabase* ItemDatabase; };
.cpp
// Fill out your copyright notice in the Description page of Project Settings. #include "TTTTT.h" #include "MyGameSingleton.h" #include "Engine.h" #include "Engine/StreamableManager.h" #include "ItemInfoDatabase.h" UMyGameSingleton::UMyGameSingleton(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer) { AssetLoader = new FStreamableManager(); //加载itemDataBase蓝图类 UObject* obj = AssetLoader->SynchronousLoad(FStringAssetReference(TEXT("/Game/AsyncLoad/NewDataAsset.NewDataAsset"))); ItemDatabase = Cast<UItemInfoDatabase>(obj); } UMyGameSingleton::~UMyGameSingleton() { if (AssetLoader) delete AssetLoader; } UMyGameSingleton* UMyGameSingleton::Get() { UMyGameSingleton* DataInstance = Cast<UMyGameSingleton>(GEngine->GameSingleton); //这里指定配置文件中指定的单例类 if (!DataInstance) return nullptr; else return DataInstance; }
上面的TEXT路径可以右键复制引用来获取
4.以这个为父类创建蓝图,并且放进项目设置里 5.创建一个Actor用来加载
.h
// Fill out your copyright notice in the Description page of Project Settings. #pragma once #include "GameFramework/Actor.h" #include "MyAsyncLoad.generated.h" UCLASS() class TTTTT_API AMyAsyncLoad : public AActor { GENERATED_BODY() public: // Sets default values for this actor's properties AMyAsyncLoad(); protected: // Called when the game starts or when spawned virtual void BeginPlay() override; public: // Called every frame virtual void Tick(float DeltaTime) override; UFUNCTION(BlueprintCallable, Category = "Async Load") bool TestAsyncLoad(); void PrintTest(); };
.cpp
// Fill out your copyright notice in the Description page of Project Settings. #include "TTTTT.h" #include "MyAsyncLoad.h" #include "ItemInfoDatabase.h" #include "MyGameSingleton.h" #include "Runtime/CoreUObject/Private/Serialization/AsyncLoadingThread.h" // Sets default values UItemInfoDatabase* _database; AMyAsyncLoad::AMyAsyncLoad() { // Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it. PrimaryActorTick.bCanEverTick = true; } // Called when the game starts or when spawned void AMyAsyncLoad::BeginPlay() { Super::BeginPlay(); } // Called every frame void AMyAsyncLoad::Tick(float DeltaTime) { Super::Tick(DeltaTime); } bool AMyAsyncLoad::TestAsyncLoad() { FStreamableManager* BaseLoader = UMyGameSingleton::Get()->AssetLoader; _database = UMyGameSingleton::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());//如果是TAssetPtr类型要加上.ToStringReference() } //请求异步加载 BaseLoader->RequestAsyncLoad(ObjToLoad, FStreamableDelegate::CreateUObject(this, &AMyAsyncLoad::PrintTest)); return true; } void AMyAsyncLoad::PrintTest() { const bool bIsMultithreaded = FAsyncLoadingThread::IsMultithreaded(); if (bIsMultithreaded)// if IsMultithreadAsyncLoad { GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Red, TEXT("YES")); } else { GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Red, TEXT("NO")); for (int32 i = 0; i < _database->MeshList.Num(); ++i) { /* FStringAssetReference asset = _database->MeshList[i].MeshResource; UObject* itemObj = asset.ResolveObject(); AActor* gen = Cast<AActor>(itemObj); if (gen != NULL) { AActor* spawnActor = GetWorld()->SpawnActor<AActor>(gen->GetClass(), FVector(0.0f, 90.0f, 50.0f), FRotator(0.0f, 0.0f, 0.0f)); }*/ AActor* MyObject = _database->MeshList[i].MeshResource.Get();// if (MyObject) { GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::White, TEXT("ReadySpawn")); //spawn actor //AActor* WorldActor = Cast<AActor>(MyObject); AActor* WorldActor = GetWorld()->SpawnActor<AActor>(MyObject->GetClass(), FVector(0.0f, 90.0f, 50.0f), FRotator(0.0f, 0.0f, 0.0f)); } } /*AsyncTask(ENamedThreads::GameThread, [&]() { GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::White, TEXT("--- UMyGameInstance::MyAsyncTask")); //SpawnActor(3); });*/ } // FString str = FString::Printf(TEXT("--- AMyChar::TestAsyncLoad callback")); // GEngine->AddOnScreenDebugMessage(1, 5.0f, FColor::Red, str); }
然后调用就可以啦
参考:http://www.lai18.com/content/1520465.html
https://forums.unrealengine.com/showthread.php?5309-TUTORIAL-C-Runtime-Async-Load-Modular-Character-(Intermediate)
http://blog.csdn.net/yangxuan0261/article/details/54408683
可参考http://blog.csdn.net/zilisen/article/details/78123332
https://zhuanlan.zhihu.com/p/79209172
http://www.dawnarc.com/2018/01/ue4资源异步加载assets-asynchronous-loading与内存释放free-memory/
