Plugin

I’ve created a plugin that allows you to configure custom Place Actors categories from Project Settings - If you are interested, please check out zomg’s editor addons - No C++ code required!

Manual setup

Create a custom Editor Module, and you can easily add new categories to the place actors toolbar.

//Get the placement mode module
IPlacementModeModule& PlacementModeModule = IPlacementModeModule::Get();
 
//Register a new category
//Handle must be unique as it's used to identify categories
FPlacementCategoryInfo Info = {
	FText::AsCultureInvariant("My Category Name"),
	FName("MyCategoryHandle"),
	TEXT("PMMyCategoryTag"),
	100
};
PlacementModeModule.RegisterPlacementCategory(Info);

Icons

Categories can be given icons if you use the overload which takes a FSlateIcon as a parameter. Engine icons can be used for this if you don’t have Custom Editor Icons

Adding C++ actors into categories

//Using a previously created placement category info variable
//you can register new values into it like so
PlacementModeModule.RegisterPlaceableItem(Info.UniqueHandle, MakeShareable(
	new FPlaceableItem(nullptr, AMyActor::StaticClass())
));
 

Adding Blueprint actors into categories

For Blueprint actors, you need to get its asset data, and an appropriate actor factory. The actor factory is most likely always UActorFactoryBlueprint, but you can get the appropriate factory using GEngine->FindActorFactoryForActorClass. (C++ actors do not need a factory.)

Below is an example of how to get a list of blueprint assets in a directory in your project, and filter all characters out, finally placing them into a category.

TArray<FAssetData> Assets;
FARFilter Filter;
Filter.ClassNames.Add(UBlueprint::StaticClass()->GetFName());
Filter.bRecursiveClasses = true;
Filter.PackagePaths = { "/Game/My/Blueprint/Characters" };
Filter.bRecursivePaths = true;
 
IAssetRegistry::Get()->GetAssets(Filter, Assets);
for(auto& Asset : Assets)
{
	UBlueprint* BP = Cast<UBlueprint>(Asset.GetAsset());
	if(!IsValid(BP))
	{
		//The BP can be invalid in some cases, such as when renaming assets
		//it can give you the old incorrect asset which will not be valid
		//and we should just skip it
		continue;
	}
	UClass* AssetClass = BP->GetBlueprintClass();
	if(AssetClass && BP->GeneratedClass->IsChildOf(ACharacter::StaticClass()))
	{
		PlacementModeModule.RegisterPlaceableItem(Info.UniqueHandle, MakeShareable(
			new FPlaceableItem(
				GEditor->FindActorFactoryForActorClass(Asset.GetClass()),
				Asset
			)
		));
	}
}