Object Library

Object library is a class that you create inside a Content browser. We can put any type of UObjects inside the library and you can access them any time we want inside your C++ code. This can help us safe lot of time if we plan our libraries carefully. Example, we could crate an object library that is full of different materials and call that MaterialLibrary. Later if we want to use some specific material, we could easily access that from the library with just created. So no need to use ConstructorHelpers class or load classes on the Runtime. All is stored nicely inside one class.


How to use Object Library?

First we need to create our library inside Content Browser. So right click on empty space, go to Miscellaneous and choose Object Library. We call that MaterialLibary.

a1

Open the created library. Set base class to be material and add some materials. I use the StarterContent materials.

a1

Now. Create a C++ class based on Actor. Add SceneComponent and Static mesh component.

UPROPERTY(VisibleAnywhere, BlueprintReadOnly, meta = (AllowPrivateAccess = "true"))
USceneComponent* RootScene;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, meta = (AllowPrivateAccess = "true"))
UStaticMeshComponent* MainMesh;

Create subobjects from them in constructor so we can see them inside blueprint components.

RootScene = CreateDefaultSubobject<USceneComponent>(TEXT("Root");
Rootcomponent = RootScene;
MainMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("MainMesh"));
MainMesh->SetupAttachment(RootScene);

Go ahead and create a blueprint class from our C++ class and set the static mesh to be Cube (Well, technically, it could be anything, but i use cube). Now we have perfectly functional class that is visible inside our game. Let’s use our object library to set new material to our mesh.

First, inside our header file, we create object pointer from UObjectLibrary class. So inside private.

UPROPERTY()
UObjectLibrary* MaterialLibrary;

Inside constructor, we use ConstructorHelpers to find the asset from content browser.

ConstructorHelpers::FObjectFinder<UObjectLibrary> ObjectLibrary(TEXT("/Game/ObjectLibrary/ObjectLibrary.ObjectLibrary"));
if (ObjectLibrary.Succeeded())
MaterialLibrary = ObjectLibrary.Object;

Now that the object library is referenced, we can have bunch of function we can do with it. You can see all the function from documents. Let’s go through the most important ones. Let’s go in BeginPlay() and get all the stuff from our library and put them into array. After that we just set the mesh material to be the seconds material of the array.

// ObjectLibrary
if (MaterialLibrary)
{
TArray<UMaterial*> Materials;
// Put all the assets to Array. This is Casted property by default!
MaterialLibrary->GetObjects<UMaterial>(Materials);
MainMesh->SetMaterial(0, Materials[1]);
}

That is the very basic way to use the library. Of course, if you don’t know what element in your array holds the material you seek, you can search it by filtering the name.

if (MaterialLibrary)
{
TArray<UMaterial*> Materials;
MaterialLibrary->GetObjects<UMaterial>(Materials);
for (auto Material : Materials)
{
FString nameToSearch = "M_Water_Ocean";
if (Material->GetName() == nameToSearch)
MainMesh->SetMaterial(0, Material);
}
}

Load assets directly from Content Browser

If you want to add multiple things in your object library and don’t want to do it manually, you can load assets directly from the path using  LoadAssetDataFromPath() or LoadBlueprintAssetDataFromPath(). These functions will get reference to assets, but they don’t load it into memory. Functions LoadBlueprintsFromPath() or LoadAssetsFromPath() are shorter, but they load the asset to memory instantly. Next, we practice how to load a BlueprintAssetData from object library. Open your object library in Content Browser and remove all elements you previously added. Set the Object Base Class to be AActor, because we don’t know what kind of actors we are getting. Remember to tick ”IsBlueprintClass”.

Now, if you want, go ahead and change the MaterialLibrary name inside our code to be something like ActorLibrary. Get reference to ObjectLibrary exactly the same way as previously, but in BeginPlay() we are going to get an class instead of an UObject. Getting class FAssetdata is a bit more harder. We cannot get it straight away. Instead, we are going to get path to that data and try load the class from the path.

// ObjectLibrary
if (ActorLibrary)
{
UE_LOG(LogTemp, Warning, TEXT("Library is set"));
// Path to our blueprints
ActorLibrary->LoadBlueprintAssetDataFromPath("/Game/Blueprints");
// Array of FAssetData
TArray<FAssetData> ActorData; 
// Load FAssetData to our array of FAssetDatas 
ActorLibrary->GetAssetDataList(ActorData);
// Start looping the array 
for (auto ActData : ActorData) {
// Get Reference to our class without all the jimboJamba paths. 
auto GeneratedClassPathPtr = ActData.TagsAndValues.Find(TEXT("GeneratedClass")); 
const FString ClassObjectPath = FPackageName::ExportTextPathToObjectPath(*GeneratedClassPathPtr); 
// We try to load class to our variable. If you know specific class. You can use that instead of AActor!
TSubclassOf<AActor> TempActor = FStringClassReference(ClassObjectPath).TryLoadClass<AActor>();
// We gonna filter out the classes. 
FString nameToSearch = "BP_DynamicActor_C";
if (TempActor->GetName() == nameToSearch) {
// Spawn the actor to center of the map, 6 meters above floor. Just to test this! 
GetWorld()->SpawnActor<AActor>(TempActor, FVector(0, 0, 600), FRotator(0, 0, 0)); } }	}

If you want little shorter version that doesn’t require FAssetData and loads the class instantly, you can use UBlueprintGeneratedClass object. This however has some downside. They aren’t working in packaged builds. So in order to make this work in package builds, you need to add that folder manually in cooking options.

ActoriLibrary->LoadBlueprintsFromPath("/Game/Blueprints");
// Create a BlueprintGeneratedClass* type (pointer)class.
TArray<UBlueprintGeneratedClass*> Blueprints;
ActoriLibrary->GetObjects(Blueprints);
// We get first element of array, just to see if it works!
auto SampleObject = Blueprints[0];
// Now we can use basic methods to load the class. In this case, we use LoadClass() function.
TSubclassOf<AActor> TmPActor = LoadClass<AActor>(this, (TEXT("%s"), *SampleObject->GetPathName()));
// We test print to log
UE_LOG(LogTemp, Warning, TEXT("Loaded actor: %s"), *TmPActor->GetName());

That’s all you need to do.

Loading anything other that blueprint classes s is very simple. You just need to load them from folder and use the same method we used in the first section of this tutorial. Again. This loads them to memory straight away. Of course, If you don’t want to load it in memory, you can use  LoadAssetDataFromPath() in this one too.  Here’s the basic version.

// Load textures from path
TextureLibrary->LoadAssetsFromPath("/Game/Textures");
TArray<UTexture2D*> ActorTextures;
// Put all the textures to our array
TextureLibrary->GetObjects(ActorTextures);
// Just for testing, let's get first element of our array
UTexture2D* TempText = ActorTextures[0];
UE_LOG(LogTemp, Warning, TEXT("Texture %s loaded!"), *TempText->GetName());

Now you know basics of how to use object library! Have fun!

Vastaa

Sähköpostiosoitettasi ei julkaista. Pakolliset kentät on merkitty *