JPNotADragon
JPNotADragon

Reputation: 2210

In my Unreal C++ class, how can I declare a UPROPERTY that will accept only instances of a specific Blueprint class?

While it is well documented how TSubclassOf<> can be used to declare a property that will only accept instances of a known C++ class, I'm in the situation where I would like my C++ AActor-derived class to contain a property that will only accept references to instances of a specific Blueprint. (That Blueprint comes from a package that does not provide C++ header files.)

Upvotes: 1

Views: 4892

Answers (1)

Wacov
Wacov

Reputation: 422

This is an interesting question so I wanted to provide one possible answer, which is a workaround with a minimal derived BP class and property reflection. I'm writing this without the engine available for compilation, so apologies if I've gotten anything wrong.

UCLASS(Blueprintable)
class AMyActor : public AActor
{
    GENERATED_BODY()

public:
    // Name of the required blueprint class property, which must be added in a derived blueprint
    constexpr FName ClassPropertyName = TEXT("BlueprintClass")

protected:
    /* Get the value of the blueprint class property. */
    UClass* GetBlueprintClass();
};


UClass* AMyActor::GetBlueprintClass()
{
    FObjectProperty* BlueprintClassProperty = FindFProperty<FObjectProperty>(GetClass(), ClassPropertyName);
    checkf(BlueprintClassProperty != nullptr, TEXT("AMyActor must used via a derived BP type with a %s property."), *ClassPropertyName.ToString()))
    
    UObject* PropertyValue = BlueprintClassProperty->GetObjectPropertyValue_InContainer(this);
    if (PropertyValue != nullptr)
    {
        return CastChecked<UClass>(PropertyValue);
    }

    return nullptr;
}

You should be able to derive this in BP and add the required BlueprintClass property. There's no other logic required on the BP side, you just get the value of the property using the GetBlueprintClass method in C++. There's a little overhead there, so you may want to cache the value e.g. on actor construction or BeginPlay.

Upvotes: 2

Related Questions