With some modification to the engine code, you can. We are currently using this method in our project, however I believe the Epic guys chose not to support this for a reason, so use at your own risk.
SGameplayAttributeWidget.cpp
Location: Engine\Plugins\Runtime\GameplayAbilities\Source\GameplayAbilitiesEditor\Private\SGameplayAttributeWidget.cpp
Search for if (Class->IsChildOf(UAttributeSet::StaticClass()
, you should locate it in the method SAttributeListWidget::UpdatePropertyOptions()
, at line 266 if you are using version 4.18.3.
Replace the entire if
block with the following code:
if (Class->IsChildOf(UAttributeSet::StaticClass()))
{
// Allow entire classes to be filtered globally
if (Class->HasMetaData(TEXT("HideInDetailsView")))
{
continue;
}
if (Class->ClassGeneratedBy)
{
const FString SkeletonPrefix(TEXT("SKEL_"));
const FString ReinstantializedPrefix(TEXT("REINST_"));
// skip skeletion classes and reinstantialized classes
if (Class->GetName().StartsWith(SkeletonPrefix) || Class->GetName().StartsWith(ReinstantializedPrefix))
{
continue;
}
}
for (TFieldIterator<UProperty> PropertyIt(Class, EFieldIteratorFlags::ExcludeSuper); PropertyIt; ++PropertyIt)
{
UProperty *Property = *PropertyIt;
if (Class->ClassGeneratedBy)
{
if (Property->GetName() == TEXT("UberGraphFrame"))
{
continue;
}
}
// if we have a search string and this doesn't match, don't show it
if (AttributeTextFilter.IsValid() && !AttributeTextFilter->PassesFilter(*Property))
{
continue;
}
// don't show attributes that are filtered by meta data
if (!FilterMetaData.IsEmpty() && Property->HasMetaData(*FilterMetaData))
{
continue;
}
// Allow properties to be filtered globally (never show up)
if (Property->HasMetaData(TEXT("HideInDetailsView")))
{
continue;
}
FString DisplayName;
if (Class->ClassGeneratedBy)
{
// remove "_C" at the end of a BP class
DisplayName = FString::Printf(TEXT("%s.%s"), *Class->GetName().LeftChop(2), *Property->GetName());
}
else
{
DisplayName = FString::Printf(TEXT("%s.%s"), *Class->GetName(), *Property->GetName());
}
TSharedPtr<FAttributeViewerNode> SelectableProperty = MakeShareable(new FAttributeViewerNode(Property, DisplayName));
PropertyOptions.Add(SelectableProperty);
}
}
This will allow you to choose attributes defined in blueprint attribute sets.
However, if you use these BP attributes, like in gameplay effect modifiers, you may find them became strange references to TRASHCLASS members after saving and reopening the editor, and crash your game. This could be one reason why the system doesn’t support BP attributes for now. While I believe this must be caused by a deeper reason, here is a workaround:
AttributeSet.cpp
Location: Engine\Plugins\Runtime\GameplayAbilities\Source\GameplayAbilities\Private\AttributeSet.cpp
Go to the end of the FGameplayAttribute::PostSerialize()
method, and append the following code:
if (Attribute)
{
UClass* AttributeSetClass = CastChecked<UClass>(Attribute->GetOuter());
UBlueprint* AttributeBlueprint = Cast<UBlueprint>(AttributeSetClass->ClassGeneratedBy);
if (AttributeBlueprint && AttributeBlueprint->GeneratedClass != AttributeSetClass)
{
UProperty* ReplacedProperty = FindFieldChecked<UProperty>(AttributeBlueprint->GeneratedClass, Attribute->GetFName());
this->SetUProperty(ReplacedProperty);
}
}
This fixes corrupted attribute references by replacing them with their correct counterparts.