Get All Fit Child Classes

Hello. I have a class (Weapon) and child classes (Grenades, Guns…) from it. I want to get all child classes what are refered to Guns. How can i do it in Blueprint without manual relisting all of them?

pretty sure that GetAllActorsOfClass returns subclasses as well, although i’m not 100% on that.

Though I’d wonder what purpose you have to do that, that you couldn’t get them using a less expensive function…

@eblade GetAllActorsOfClass (with Guns as the actor class) will return all guns and all classes that inherit from guns.

2 Likes

I want to create a box that generates a random weapon outta selected classes. I need logic that returns classes instead of already existing actors.

I think the OP means before instantiation.

@ClockworkOcean In c++ you can use UOBject GetDerivedClasses method. Not sure BP has the equivalent.

1 Like

I don’t think so. @Username0520 you just need to put the classes in an array once, then you can randomly choose from it and spawn.

The problem: i have lots of classes and often create new once. This is why i want to create some logic for automatisation.

you kinda have to create a list yourself, otherwise they may not exist in the packaged output

You only have to create the array once, and add one when you make a new class.

You can do it with a c++ blueprint library in a couple of steps.

.h (header file)

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "Kismet/BlueprintFunctionLibrary.h"
#include "MyBlueprintFunctionLibrary.generated.h"

/**
 * 
 */
UCLASS()
class REPLACE_WITH_YOUR_API UMyBlueprintFunctionLibrary : public UBlueprintFunctionLibrary
{

public:
	
	UFUNCTION(BlueprintCallable)
	static TArray<UClass*> GetDerived(UClass* PassedClass);

	GENERATED_BODY()
	
};

.cpp

// Fill out your copyright notice in the Description page of Project Settings.

#include "MyBlueprintFunctionLibrary.h"
#include "UObject/UObjectHash.h" 

TArray<UClass*> UMyBlueprintFunctionLibrary::GetDerived(UClass* PassedClass) {
	TArray<UClass*> ret;
	if (PassedClass) {		
		GetDerivedClasses(PassedClass, ret, true);				
	}
	return ret;
}
1 Like

worth noting that you’l still need to actually reference all the weapon classes via hard ref or via AlwaysPackage in INI otherwise you’re not going to have the results in t he packaged game output

Unfortunately there is no soft class variant of the function.

I suggest the following solution:

  1. Keep your parent and children’s classes in the same folder.

image

  1. Create a BlueprintFunctionLibrary and add this function:

  1. Call the function anywhere in your project:

There is one important note. This works in PIE and packaging build but doesn’t work in standalone mode.

I hope it’ll be helpful for you.

My Products

1 Like

This code works for classes that aren’t loaded yet (make sure to add them to asset manager, in project settings).

This code was posted elsewhere (sorry I don’t have the link or know the original author); I have updated it to compile with 5.1 API changes.

TArray<TSubclassOf<UObject>> UMyBlueprintFunctionLibrary::GetSubclassesOf(TSubclassOf<UObject> ParentClass)
{
	TArray<TSubclassOf<UObject>> Subclasses;

	// ~~~C++ classes~~~

	for (TObjectIterator< UClass > ClassIt; ClassIt; ++ClassIt)
	{
		UClass* Class = *ClassIt;

		// Only interested in native C++ classes
		if (!Class->IsNative())
		{
			continue;
		}
		// Ignore deprecated
		if (Class->HasAnyClassFlags(CLASS_Deprecated | CLASS_NewerVersionExists))
		{
			continue;
		}
		// Check this class is a subclass of ParentClass
		if (!Class->IsChildOf(ParentClass))
		{
			continue;
		}
		// Add this class
		Subclasses.Add(Class);
	}

	// ~~~Blueprint classes~~~

	FAssetRegistryModule& AssetRegistryModule = FModuleManager::LoadModuleChecked< FAssetRegistryModule >(FName("AssetRegistry"));
	IAssetRegistry& AssetRegistry = AssetRegistryModule.Get();
	// The asset registry is populated asynchronously at startup, so there's no guarantee it has finished.
	// This simple approach just runs a synchronous scan on the entire content directory.
	// Better solutions would be to specify only the path to where the relevant blueprints are,
	// or to register a callback with the asset registry to be notified of when it's finished populating.
	TArray< FString > ContentPaths;
	ContentPaths.Add(TEXT("/Game/Blueprints"));
	AssetRegistry.ScanPathsSynchronous(ContentPaths);

	FName BaseClassName = ParentClass->GetFName();
	FName BaseClassPkgName = ParentClass->GetPackage()->GetFName();
	FTopLevelAssetPath BaseClassPath(BaseClassPkgName, BaseClassName);

	// Use the asset registry to get the set of all class names deriving from Base
	TSet< FTopLevelAssetPath > DerivedNames;
	FTopLevelAssetPath Derived;
	{
		TArray< FTopLevelAssetPath > BasePaths;
		BasePaths.Add(BaseClassPath);

		TSet< FTopLevelAssetPath > Excluded;
		AssetRegistry.GetDerivedClassNames(BasePaths, Excluded, DerivedNames);
	}
	FARFilter Filter;
	FTopLevelAssetPath BPPath(UBlueprint::StaticClass()->GetPathName());
	Filter.ClassPaths.Add(BPPath);
	Filter.bRecursiveClasses = true;
	Filter.PackagePaths.Add(*ContentPaths[0]);
	Filter.bRecursivePaths = true;

	TArray< FAssetData > AssetList;
	AssetRegistry.GetAssets(Filter, AssetList);

	for (auto const& Asset : AssetList)
	{
		// Get the the class this blueprint generates (this is stored as a full path)
		FAssetDataTagMapSharedView::FFindTagResult GeneratedClassPathPtr = Asset.TagsAndValues.FindTag("GeneratedClass");
		{
			if (GeneratedClassPathPtr.IsSet())
			{
				// Convert path to just the name part
				const FString ClassObjectPath = FPackageName::ExportTextPathToObjectPath(GeneratedClassPathPtr.GetValue());
				//const FString ClassName = FPackageName::ObjectPathToObjectName(ClassObjectPath);
				const FTopLevelAssetPath ClassPath = FTopLevelAssetPath(ClassObjectPath);
				

				// Check if this class is in the derived set
				if (!DerivedNames.Contains(ClassPath))
				{
					continue;
				}
				FString N = Asset.GetObjectPathString() + TEXT("_C");
				Subclasses.Add(LoadObject<UClass>(nullptr, *N));
			}
		}
	}
	return Subclasses;
}

Edit - source: Finding all classes/blueprints with a given base — kantan

2 Likes