I’m working in blueprints with editor utilities and need names of all BPs of specific class. E.g. if I have a BP_ArrowBase and inheriting from it: BP_ArrowFIre, BP_ArrowIce. I’d like to get the names of the latter two.
I tried using ‘Get Assets by Class’ with BP_ArrowBase class but it returns nothing. Eventually I found that all blueprints report as being of Blueprint class. So I can get a list of all blueprints but then their class checking doesn’t work either:
Afaik this is not simple because assets/packages are not always loaded at all times, and asset registry does not know about blueprints hierarchical inheritance.
However, asset registry has ability to search by tags, and blueprints do store their parent class path and their closest native parent class path into tags.
Unfortunately searching by tags is not exposed to blueprints so you’ll need C++ utility to get anything done on that front.
Here is an example utility that searches blueprints children of a given native parent class :
#include "AssetRegistry/AssetRegistryModule.h"
bool USomeUtility::FindBlueprintsChildOf(TSubclassOf<UObject> InNativeClass, TArray<FAssetData>& FoundAssets)
{
if (!InNativeClass || !InNativeClass->IsNative())
return false;
FAssetRegistryModule& AssetRegistryModule = FModuleManager::LoadModuleChecked<FAssetRegistryModule>("AssetRegistry");
TMultiMap<FName, FString> TagsValues;
// All native CDOs should be in memory - we can look up native subclasses of InNativeClass
for (FThreadSafeObjectIterator It(InNativeClass); It; ++It)
{
UClass* Class = It->GetClass();
if (Class->IsNative() && Class->ClassDefaultObject == *It)
{
TagsValues.AddUnique(FBlueprintTags::NativeParentClassPath, FString::Printf(TEXT("%s'%s'"), *Class->GetClass()->GetName(), *Class->GetPathName()));
}
}
return AssetRegistryModule.Get().GetAssetsByTagValues(TagsValues, FoundAssets);
}
I am adding all native subclasses of the provided class, so if you supply “Pawn” it will effectively also look for “Character” subclasses and “SpectatorPawn” subclasses etc.
You can theoretically achieve something similar with a blueprint base class, using the FBlueprintTags::ParentClassPath tag instead, however if you also need to fetch grandchildren you’ll probably have to implement some additional recursion.
This option worked for me only after the replacement FString::Printf(TEXT("%s'%s'"), *Class->GetClass()->GetName(), *Class->GetPathName()) on FObjectPropertyBase::GetExportPath(Class)
Since UE5 there is a new node GetBlueprintAssets designed to do exactly that - find blueprint child classes of specified parent class (native or BP). It is also based on GetDerivedClassNames and does a recursive search using assets’ ParentClassPath tag.