Knowledge Base: How To: Create New Assets in C++

Article written by Cody A.
When writing editor scripts or plugins, it may be useful to be able to programmatically create a new asset that appears in the content browser. There are a few helper functions available to he…

https://dev.epicgames.com/community/learning/knowledge-base/wzdm/unreal-engine-how-to-create-new-assets-in-c

14 Likes

Hi, can somebody provide a small sample how this works with DataAssets? Can I use UDataAssetFactory here? This snippet is a good starting point, but a more complete example would be much appreciated, thanks!

1 Like

If you wish to utilize DataAssets in this context, you can achieve this by making a minor adjustment to the default code:

Instead of the original code:

UBlueprintFactory* MyFactory = NewObject<UBlueprintFactory>(UBlueprintFactory::StaticClass()); // This line is optional; a default factory will be used if omitted
UObject* NewObject = AssetToolsModule.Get().CreateAsset(Name, PackagePath, UBlueprint::StaticClass(), MyFactory);

Use the following code:

UDataAssetFactory* MyFactory = NewObject<UDataAssetFactory>(UDataAssetFactory::StaticClass());
MyFactory->DataAssetClass = UPrimaryAssetLabel::StaticClass();
UObject* NewObject = AssetToolsModule.Get().CreateAsset(Name, PackagePath, UDataAsset::StaticClass(), MyFactory);

In my case, I employed a UPrimaryAssetLabel type for my UDataAsset; however, you are free to choose the appropriate type for your specific needs.

Inside the constructor of UDataAssetFactory in the Unreal Engine source code, we can observe that it employs:
SupportedClass = UDataAsset::StaticClass();

Hence, when we employ the CreateAsset function with this Factory, it’s important to replace “UBlueprint” with “UDataAsset”.

The line MyFactory->DataAssetClass = UPrimaryAssetLabel::StaticClass(); is crucial to avoid crashes. We can deduce its necessity by inspecting the UAssetToolsImpl::CreateAsset function, which invokes UDataAssetFactory::FactoryCreateNew, utilizing the TSubclassOf<UDataAsset> DataAssetClass parameter.
This parameter is also present in UDataAssetFactory, and UPrimaryAssetLabel inherits from UDataAsset.

3 Likes

May I ask, what is “PackageName” for an asset?
If I wanna create a BP inherit from a AActor, what “PackageName” should I set for it?

I’m Taiwanese, forgive about my english.
Here’s the thing, i’ve encountered a problem that I want to programmatically generate assets, like inventory items. Yeah, I know the way of using AssetData, but some object is already set, so I still want to create a blueprint asset into content.

Here is it.
Before defining your own generation code, you have to define your object factory first.

UCLASS( hidecategories = Object, collapsecategories)
class LYRAGAME_API UBPFactory_MyObject: public UBlueprintFactory
{
	GENERATED_BODY()

	UBPFactory_MyObject();

	virtual UObject* FactoryCreateNew(UClass* Class, UObject* InParent, FName Name, EObjectFlags Flags, UObject* Context, FFeedbackContext* Warn, FName CallingContext) override;
};

UBPFactory_MyObject::UBPFactory_MyObject()
{
	bCreateNew = true;
	bEditAfterNew = true;
	SupportedClass = UBlueprint::StaticClass();
	ParentClass = ULyraInventoryItemDefinition::StaticClass();
	BlueprintType = BPTYPE_Normal;
}

UObject* UBPFactory_MyObject::FactoryCreateNew(UClass* Class, UObject* InParent, FName Name, EObjectFlags Flags, UObject* Context, FFeedbackContext* Warn, FName CallingContext)
{
	return FKismetEditorUtilities::CreateBlueprint(ParentClass, InParent, Name, BlueprintType, UBlueprint::StaticClass(), UBlueprintGeneratedClass::StaticClass(), CallingContext);
}


ObjectFactory is the main method of creating your object.

After creating BlueprintFactory for your object, back to CreatePackage section.

// Create object and package
UPackage* package = CreatePackage(*PackageName);
UBPFactory_MyObject* MyFactory = NewObject<UBPFactory_MyObject>(UBPFactory_MyObject::StaticClass()); // Use tour custom object factory

UObject* NewObject = AssetToolsModule.Get().CreateAsset(Name, OutPackagePath, UBlueprint::StaticClass(), MyFactory);

FSavePackageArgs SaveArgs = FSavePackageArgs();
SaveArgs.SaveFlags = RF_Public | RF_Standalone;

UPackage::Save(package, NewObject, *FPackageName::LongPackageNameToFilename(PackageName, FPackageName::GetAssetPackageExtension()), SaveArgs);

// Inform asset registry
AssetRegistry.AssetCreated(NewObject);

// Tell content browser to show the newly created asset
TArray<UObject*> Objects;
Objects.Add(NewObject);

That’s much all for generating customed blueprint assets.

Hi! I’m having a problem where I can’t seem to use the StaticClass() of the UDataAssetFactory. It gives a linkin error. Do you know what this could be?