UE4非同步載入資源
阿新 • • 發佈:2019-02-14
1.建立一個C++資源庫ItemInfoDatabase.h
.h
.cpp#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(); };
// 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
.cpp// 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; };
// 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路徑可以右鍵複製引用來獲取
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
http://www.dawnarc.com/2018/01/ue4%E8%B5%84%E6%BA%90%E5%BC%82%E6%AD%A5%E5%8A%A0%E8%BD%BDassets-asynchronous-loading%E4%B8%8E%E5%86%85%E5%AD%98%E9%87%8A%E6%94%BEfree-memory/