Working with DataAsset in C++

Hi,

I am trying to make a plugin that import assets from an external system that provide XML files for the game to use. I followed as much as possible tutorial and documentation but I keep hitting wall after wall.

So here the questions:

1 - How do you create a UDataAsset in C++ (I have created a new UDataAsset but I cannot create it in c++, I can only do it from the editor. I could make the code to find existing asset using the IAssetRegistry and GetAssetsByClass then using FindByPredicates. But if it doesn’t already exist I need to create it and fill it with what is in the XML.

2 - Is there any file explorer pre existing tool in the editor ? cause I couldn’t find any, Maybe an existing plugin I missed ?

3 - Is it possible to create multiple assets at once from one file that you drag & drop in the content ?

Thanks

would this this be a proper way to do it ? the assert would be register in the registry and appear in the content ?

FString assetName("MyAssetType_");
assetName.Append(UTF8_TO_TCHAR( myassetname ));

FAssetData newAsset(FName(), FName("Asset"), FName(*assetName), FName("MyAssetType"));

UMyAssetType* newAsset = Cast<UMyAssetType>(newAsset.GetAsset());

newAsset ->param1= myParam1;
newAsset ->param2= myParam2; 
MyMainAsset->AssetList.AddUnique(Cast<UMyAssetType>(newAsset ));

or maybe using AssetManager.AddDynamicAsset ? I really need to find an example somewhere

this almost work, but the asset doesn’t appear in the content. How do you make you code created asset appear in the content (all my code is in an editor module, so I am pretty sure editor must be capable of doing such a thing)

 UMyAssetType* newAsset = NewObject<UMyAssetType>();
 newAsset ->param1= myParam1;
 newAsset ->param2= myParam2; 
 MyMainAsset->AssetList.AddUnique(newAsset);

the UDataAsset is visible in MyMainAsset but cannot be found or reused in component or other actor in the game.

Hi,

Thanks for the answer, I already did this tutorial and I have a factory for my main asset, I thought since the other asset were a lot simpler and only data container I could use UDataAsset for them.

Anyway, I also tried to make them asset with factory and I still cannot make them appear in the content browser.

I tried the following but it is another failure :

FString FinalPackageName = TEXT("/MyGame/Assets");
FString assetName = FString(TEXT("MyAssetSpec_"));
										 
assetName.Append(FString(TEXT(nameFromXML)));
UPackage* Package = CreatePackage(NULL, *FinalPackageName);
UPackage* OutermostPkg = Package->GetOutermost();

auto factory = NewObject<UMyAssetSpecAssetFactoryNew>();

UObject* TestObj = factory->FactoryCreateNew(UMyAssetSpec::StaticClass(), OutermostPkg, *assetName, RF_Standalone | RF_Public, NULL, GWarn);
UMyAssetSpec* newAsset = Cast<UMyAssetSpec>(TestObj);
									FAssetRegistryModule::AssetCreated(TestObj);
TestObj->MarkPackageDirty();
Package->SetDirtyFlag(true);
TestObj->PostEditChange();
TestObj->AddToRoot();

also just to clarify, the main asset import is working fine, when I drag & drop my xml it creates my main asset properly and the factory is working, but my XML contains more information that I want to extract, so I want to create multiple assets from this XML file , not just one.

If you plan to do something more advance like importing, you should not be using UDataAsset.

Any class can be asset, It just need to have AssetTypeActions registered and UFactory which class reproducible for asset creation and importing. UDataAsset is a shortcut that avoids those steps if you want to create very simple asset type that only contains properties. Aspecially that AssetTypeActions in requires manual registering in module class which in game module (C++ project) it is replaced in macro and would require programmer to setup proper module class to make it work. If you want to make something more then simple property holding you need to create proper asset type

Since this is quite extensive topic, i will just link tutorial showing how to create asset type properly with UFactory and AssetTypeActions:

Once oyu have proper UFactory it will have a function that creates asset. It does not cover importing, but everything oyu need for that is in UFactory, so study other UFactories of importable assets to learn more

I found why the code wasn’t working, it was because in the name of the Package /Game/ need to be put at the beginning.

so this code was actually working, just the package name was wrong. (don’t either forget the / at the end of the name)

Also just found that there is a AdditionalImportedObjects member in the UFactory, if I had found this earlier I would have win few days of development. You can just create asset with any factory and push it in this array.

 FString FinalPackageName = TEXT("/Game/MyGame/Assets/");
 FString assetName = FString(TEXT("MyAssetSpec_"));
                                          
 assetName.Append(FString(TEXT(nameFromXML)));
 UPackage* Package = CreatePackage(NULL, *FinalPackageName);
 UPackage* OutermostPkg = Package->GetOutermost();
 
 auto factory = NewObject<UMyAssetSpecAssetFactoryNew>();
 
 UObject* TestObj = factory->FactoryCreateNew(UMyAssetSpec::StaticClass(), OutermostPkg, *assetName, RF_Standalone | RF_Public, NULL, GWarn);
 UMyAssetSpec* newAsset = Cast<UMyAssetSpec>(TestObj);
                                     FAssetRegistryModule::AssetCreated(TestObj);
 TestObj->MarkPackageDirty();
 Package->SetDirtyFlag(true);
 TestObj->PostEditChange();
 TestObj->AddToRoot();