How to use ConstructorHelpers::FObjectFinder

I am kind of new to the Unreal C++ arena. I know C++ and I primarily code within the Unity atmosphere, but I am not sure what exactly I am doing wrong with this script. I simply want to find a blueprint in the content browser and spawn it later down the line. Right now I have just been having trouble finding the object itself. I followed a different forum on how to spawn an actor in C++ but for some reason my code cannot find the objects.


// this function is simply supposed to return if I have found the object needed to spawn in

bool AActorSpawnerCPP::GetNewActorByName(FString newActorName) 
{
	bool foundActor = false;
	// file location should be:
	// Blueprint'/Game/ObjectsToBeAdded/Blueprints/
	// specifically Blueprint'/Game/ObjectsToBeAdded/Blueprints/BP.BP'
	//  or it could be Blueprint'/Game/ObjectsToBeAdded/Blueprints/PleaseWork.PleaseWork'
	FString tempFileLoc = fileLocation + newActorName + "."+newActorName;

	// this is the hard coded way for the object but it still does not find it
	//tempFileLoc = "/Game/ObjectsToBeAdded/Blueprints/BP.BP";


	static ConstructorHelpers::FObjectFinder<UBlueprint> lookForObj(*tempFileLoc);

	if (lookForObj.Object != NULL) {
		TSubclassOf<AActor> BlueprintVar;
		BlueprintVar = (UClass*)lookForObj.Object->GeneratedClass;
		foundActor = true;
	}
	else {
		UE_LOG(LogTemp, Error, TEXT("Could not find %s in the location: %s"), *newActorName, *tempFileLoc);
	}
	return foundActor;
}

It’s gotten to the point I do not know what I am doing wrong and need someone with more expertise to steer me in the right direction.

Thanks for whatever

1 Like

ConstructorHelpers need to be in constructor, which is AActorSpawnerCPP::AActorSpawnerCPP()
Otherwise, use LoadObject

Regarding the file location, you can use right-click on the asset in content browser, then choose Copy Reference, and set it to the file path

1 Like

Thank you for leading me down the right path! I thought I would share everything else that I came across to solve my problem in case anyone else stumbles here. The end result is at the bottom of the post for others.

How to Use C++ in Unreal Engine 5 - Beginner Tutorial
To start off I was going off this video here to get started but I needed to spawn more than one type of actor blueprint in one spot. So I set out to dynamically change this value during the game.

Load Object vs Static Load Object
The first thing I came across while researching LoadObject is that that it is just a wrapper around calling StaticLoadObject before casting it to type T. It does omit the seventh argument bAllowObjectReconciliation. The LoadObject version saves a few keystrokes, but omits the bAllowObjectReconciliation term. In order to set this value (default: true) you must call StaticLoadObject directly. Changing this to false will cause the inner workings to skip the pre-emptive call to FindObject thereby requiring a LoadPackage call. So I decided to use StaticLoadObject.

StaticLoadObject
Next was learning the spawn parameters, which were quite easy to find

  • The first param will be the class you want with “::StaticClass()” Example: AActor::StaticClass()

  • The articles I was reading said that the InOuter might be who you want to be the parent of the object youre spawning?

  • The next part is a tad confusing… Name is where you put the file path/ the reference from the content browser and FilePath you cna just set to NULL

  • You can find the LoadFlags online and what they do here: ELoadFlags

  • I am not sure what Sandbox does… but you can just set that to null too if you just need the object.

I had trouble getting the blueprint to spawn because the class that came out of the StaticLoadObject. I was using AActor at this time. SO after more research I learned the proper way spawn the blueprint as an actor which I came to this forum post:
How to spawn a blueprint actor via C++

Here is the final solution and it works! Thanks for reading.
Here is the header file:

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "ActorSpawnerCPP.generated.h"

UCLASS()
class SPACEFORCEUNREAL_API AActorSpawnerCPP : public AActor
{
	GENERATED_BODY()
	
public:	
	// Sets default values for this actor's properties
	AActorSpawnerCPP();


	UFUNCTION(BlueprintCallable, Category = "Abilities")
		void SpawnNewActor();

	UFUNCTION(BlueprintCallable, Category = "Abilities")
		bool GetNewActorByName(FString newActorName);


	UPROPERTY(EditAnywhere)
		TSubclassOf<AActor> actorBPToSpawn;

	UFUNCTION(BlueprintCallable)
		void SetFileLocation(FString newLoc);

	UPROPERTY(EditAnywhere)
		FString fileLocation;


protected:
	// Called when the game starts or when spawned
	virtual void BeginPlay() override;

public:	
	// Called every frame
	virtual void Tick(float DeltaTime) override;

};

Here is the Finished Code:

bool AActorSpawnerCPP::GetNewActorByName(FString newActorName) 
{
	bool foundActor = false;
	// file location should be:
	// Blueprint'/Game/ObjectsToBeAdded/Blueprints/
	// specifically Blueprint'/Game/ObjectsToBeAdded/Blueprints/BP.BP'
	//  or it could be Blueprint'/Game/ObjectsToBeAdded/Blueprints/PleaseWork.PleaseWork'
	FString tempFileLoc = fileLocation + newActorName + "."+newActorName;

	// this is the hard coded way for the object but it still does not find it
	tempFileLoc = "Blueprint'/Game/ObjectsToBeAdded/Blueprints/PleaseWork.PleaseWork'";

	UObject* newActor = Cast<UObject>(StaticLoadObject(UBlueprint::StaticClass(), NULL, *tempFileLoc, NULL, LOAD_None, NULL));
	UBlueprint* GeneratedBP = Cast<UBlueprint>(newActor);

	if (newActor != nullptr) {

		actorBPToSpawn = GeneratedBP->GeneratedClass;

		foundActor = true;
	}
	else {
		UE_LOG(LogTemp, Error, TEXT("Could not find %s in the location: %s"), *newActorName, *tempFileLoc);
	}
	return foundActor;
}

This is called later down the Line:


// a simple 
void AActorSpawnerCPP::SpawnNewActor()
{

	if (actorBPToSpawn != NULL)
	{
		FActorSpawnParameters spawnParams;
		spawnParams.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AdjustIfPossibleButAlwaysSpawn;

		GetWorld()->SpawnActor<AActor>(actorBPToSpawn, GetActorTransform(), spawnParams);
	}
	else {
		UE_LOG(LogTemp, Error, TEXT("actorBPToSpawn is null"));
	}
	
}

This is a personal opinion.

I think using constructor helpers is a bad idea. There are other ways to do the same and not depend of strings PATHs which will only cause problems when renaming o moving files.

Try reparenting Blueprints or UDeveloperSettings instead (I think it’s better)

The reason I was doing it this way was to coincide with a structure and data table for showing objects. The data table holds all information about the object and name of the object to spawn. Usually I would do this in a blueprint but I have about 80 different objects that can be spawned at this one place. I didnt want to make 80+ variables or objects in the scene so I set out to dynamically add them from the content browser like using a Resource.Load in Unity

Would these methods work for this situation? If so could I have an example or shown where to look for this?

I was talking about this (it’s the path of a file). When you want to rename or move files you will see that having this like this is a nightmare.

I’m Not familiar with that Unity tool… but from what you’re saying it sounds like what you’re looking for is the factory design pattern…

You only need the type of class to spawn all the objects you want