First I’m still very new to GAS. I am trying to prototype a multiplayer game with it in which we can switch between multiple characters (spawn a new one, possess it, destroy the old one).
I naturally thought it was a good idea to maintain a map for my AbilitySystemComponents and AttributeSet in the PlayerState (I don’t want to lose my characters attributes when they are destroyed). I’m instantiating and registering my AbilitySystemComponents and AttributeSets in the OnConstruction method of the PlayerState. Then in the character’s PossessBy and OnRep_PlayerState I’m initializing the Avatar and Owning actors by grabbing the ASC corresponding to the type of character I’m possessing. However it doesn’t seems viable as replication isn’t working well and I’m having a hard time using ShowDebug AbilitySystem that isn’t properly displaying my attributes.
Do you have any good practice recommendation for this case ?
Hi, have you created several AbilitySystemComponents in the PlayerState’s constructor? Or does the PlayerState have a mapping of AbilitySystemComponents for each character type? Both?
I recommend creating one ASC in the PlayerState and then refresh/grant abilities based on the character that’s possessed. With this approach, attribute values will persist on the PlayerState across characters.
If you want to, you can modify attributes by applying effects to different character types eg. you possess a new character who moves much faster so you could set their speed to be higher. A character’s default stats could use a GameplayEffect class which you apply in the PossessedBy() function.
Have you implemented the IAbilitySystemInterface as well? Your PlayerState and each character will need to implement this interface and the GetAbilitySystemComponent() function.
The PlayerState grabs the ASC attached directly to it while the characters point to the ASC on the PlayerState (assign in a character’s PossessedBy() function).
Consider having a parent character class that handles a lot of the initial set up eg. when any character is possessed, grant default abilities and effects. You could create child classes in editor where you can modify what abilities and effects are granted on a per character basis.
For now indeed I have a TMap of ASC and a TMap of AttributeSets, using the type of my character as a key (but I’m creating them in the OnConstruction method, not the constructor, I need to know which types I want as keys from another serialized TArray).
Then I’ve implemented the GetAbilitySystemComponent() in the player state (AND the characters) that returns the ASC from the TMap using the currently possessed Pawn type.
I recommend creating one ASC in the PlayerState and then refresh/grant abilities based on the character that’s possessed. With this approach, attribute values will persist on the PlayerState across characters.
Do you mean that some how one ASC is able to automagically handle multiple avatars ? Let’s say I have 3 character types with a health attribute, when I’m destroying the currently possessed pawn and respawning a new one, I can init it with the same ASC and the FGameplayAttributeData (from the attribute set on the playerstate) will still have the same current values ?
Do you mean that some how one ASC is able to automagically handle multiple avatars ? Let’s say I have 3 character types with a health attribute, when I’m destroying the currently possessed pawn and respawning a new one, I can init it with the same ASC and the FGameplayAttributeData (from the attribute set on the playerstate) will still have the same current values ?
Not quite automagically but yes that’s exactly what I’m saying. With the PlayerState approach, its ASC and attributes persist since it has not been destroyed or respawned, only the possessed character. You can still modify attributes on a per character basis, like I mentioned with the movement speed example above. The difference is not having multiple ASCs, but having one ASC whose abilities, attributes and effects are updated dynamically.
This approach also works in the case of AI characters if you want to keep things manageable and consistent with a common parent character. There’s a class variable in the AI controller called Wants Player State. If the AI inherits from the common parent character and its controller wants a PlayerState, it then also has its own ASC ready to go.
If your Actor will respawn and need persistence of Attributes or GameplayEffects between spawns (like a hero in a MOBA), then the ideal location for the ASC is on the PlayerState.
I ended up having only one ASC on the PlayerState and a Map of AttributeSets per character type, that I’m dynamically removing/adding on the ASC on player possession.