Creating a UObject in a Construction Script

Hey all,

In a project I’m working on, I have Item Objects (UObjects) and a single Item Actor (AActor) that represents Items in the Game World. The Objects have information on the Static Mesh and Materials the Actor should adopt. The Actor has a reference to the object class.

However, I cannot not pull that information from the Object until it’s instantiated, and as far as I know only at runtime in the Actor’s construction or begin play.

Is there a way to perform this action in the construction script of the Actor so that I can see them in the editor while I’m world-building?

I appreciate the advice!

Hi Otter,

In C++, the FActorSpawnParameters has a bool called bAllowDuringConstructionScript - set to true and you can spawn things.

Hello RecourseDesign,

Could you provide an example of how I might use that struct in creating an Object? I know its a param in spawning an actor.

My actor’s construction script:

AItemActor::AItemActor()
{
	PrimaryActorTick.bCanEverTick = false;
	bReplicates = true;
	bReplicateUsingRegisteredSubObjectList = true;

	//Create Static Mesh for the Item Actor
	StaticMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("Default Static Mesh"));

	ItemData = NewObject<UItemObject>(this, TEXT("ItemData"), RF_NoFlags, ItemClassTemplate);

	if (ItemData)
	{
		auto StaticMeshAsset = ConstructorHelpers::FObjectFinder<UStaticMesh>(*ItemData->ActorStaticMesh.ToSoftObjectPath().ToString());
		if (StaticMeshAsset.Object) StaticMesh->SetStaticMesh(StaticMeshAsset.Object);

		//Set all materials of static mesh with the supplied array from ItemObj
		for (size_t i = 0; i < StaticMesh->GetNumMaterials(); i++)
		{
			StaticMesh->SetMaterial(i, LoadObject<UMaterialInterface>(NULL, *ItemData->ActorStaticMeshMaterials[i].ToString(), NULL, LOAD_None, NULL));
		}
	}
}

Sorry, my mistake - I was thinking spawning new actors not objects.

For something like that, you may be better using Actor Components that contain the mesh and material information?

1 Like

Thanks! I’ll look into it.

Unfortunately, I’m also running into an issue where the class is not valid at any point on construction, therefore I cannot create the Item or get its information through GetDefaultObject().

I think the easiest solution would be just to have a DataTable in the Actor of all the Items and their associated meshes and go from there.

1 Like

So to wrap this up for anyone’s future reference,

I figured out the problem:

The Item Object Class variable (to spawn the Item Object) was being set in the child BP class (in the details panel), therefore it was not accessible yet to the Construction script of the C++ class.

So I moved down the line of functions called and implemented the code to set the Static Mesh from the Item Data during PostInitProperties(), like so:

void AItemActor::PostInitProperties()
{
	Super::PostInitProperties();

	if (!ItemObject)
	{
		if (ItemObjectClass.IsValid() || ItemObjectClass.IsPending())
		{
			//Load Item Object Class Ptr and spawn Item
			auto ValidItemClass = ItemObjectClass.LoadSynchronous();

			ItemObject = UFunctionLibrary::CreateItemObject(ValidItemClass, ItemCount);
		}
	}

	if (ItemObject && StaticMesh)
	{
		//Set StaticMesh
		if (ItemObject->ItemMesh.IsValid() || ItemObject->ItemMesh.IsPending())
		{
			UStaticMesh* ItemMesh = ItemObject->ItemMesh.LoadSynchronous();

			if (ItemMesh) StaticMesh->SetStaticMesh(ItemMesh);
		}
	}
}