Hello there.
I’m using GAS for my project with both C++ and Blueprints, and I’ve noticed that my character may have duplicated attributes when I initialize the attribute set using the “Default Starting Data” field.
I think I found the issue, and I would like to share the result of my investigation in case you are facing the same problem.
I created my Ability System and the Attribute Set Components in my Character’s constructor, as suggested in the official documentation, and then I set the starting data table as I showed in the previous picture.
In case you are not interested in why the issue occurs, but only in the fix, then do this:
-
Instantiate both the Ability System and Attribute set components in your character class’s constructor; IMPORTANT: the AttributeSet instance must be created with the name “AttributeSet”
-
When you set your starting data table in the ability system component, keep the Attributes field of type “AttributeSet” ( the type must match the name of your attribute set in the class constructor)
-
[Optional] To clear the ability system component metadata, I suggest doing a reparenting of your BP character, e.g. change your BP character’s parent class to ACharacter and then back to your custom character class. Unfortunately, this procedure leads to resetting all the data of your character.
Here’s how I instantiate my GAS components
Now, let’s dive into why this issue happens.
Let’s start by pointing our attention to these two behaviors of the Ability System Component:
- As you may know, the ability system component automatically detects the owner’s attribute set. This happens in the UAbilitySystemComponent::InitializeComponent(), starting from line 75.
- In case you have set the Starting Data Table, the Ability System Component initializes the Attributes in the OnRegister() method, as can be seen here
The method UAbilitySystemComponent::GetOrCreateAttributeSubobject, as its name suggests, tries to retrieve the involved attribute set and, in case it fails, it creates a new instance of it.
Now, the issue of the duplicated attribute sets relies on the fact that when a character is spawned, the OnRegister() is called before the InitializeComponent() method, which leads to a situation where the Ability System Component didn’t retrieve the spawned attribute set components in the character yet, thus the UAbilitySystemComponent::GetOrCreateAttributeSubobject() creates a new attribute set with the name “AttributeSet” (that’s why I said that the name of the attribute set must be “AttributeSet” in the character’s constructor) instance instead of retrieving the created one.
Then, in the InitializeComponent() method, the attribute set is searched, and then the AddUnique method is executed. This method looks in the spawned attributes for an equal attribute set, and the comparison method also involves the name of the instance (that’s why the names of the attribute set created in the class’s constructor and the Attributes field in the starting data must match!). In case you have a mismatch between the AttributeSet’s name in your constructor and the Attributes field set in the Starting data, you’ll have the attribute set duplicated.
The fix that I’ve proposed is one of many; its limitation is the fact that you have to be very careful about how you name and set your attribute sets, but at least you don’t have to change the engine’s code. Maybe a more robust fix would be to move the InitFromDataTable() invocation from the OnRegister() to the InitializeComponent() method right after the AttributeSet retrieval, or even better, merge these two logics when retrieving the spawn attribute set in the actor (in this case, the line AbilitySystem→AddSpawnedAttribute(AttributeSet) will be redundant).
I guess this is up to you and your project’s requirements.
Cheers!





