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%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/