[Gameplay Ability System] How can I level up an ability? additionally, how can i change what changes when ability levels up?

I’m trying to give the player an ability and add level up- so far what i’ve come with is a dictionary that holds the ability + the level it’s supposed to have, then whenever it levels up i revoke the ability, then grant it again with the new level. likeso:

is this the right way? or is there a way to simply level up the ability with a GESpecHandle or something similar?

additionally, I would like abilities to change depending on the level. For example, level 1 fires one projectile, level 2 fires 2 projectiles, level 3 increases the damage of the projectiles. How can I achieve this? should I simply make new Abilities for each level?

Thank you in advance.

I am by no means an expert on GAS, so I will refer you to one. You seem to be definitely going in the right direction (depending on if it is important for your project, that an active ability stays active while leveling up).

GESpecHandle would be for a Gameplay Effect, what you want is the AbilitySpecHandle. I would recommend doing this in C++ rather than blueprint (personal preference which has worked well so far). If you would like a code example, just reply to this post and I will try and add one for you.


Edit:

Oops, forgot it was a two part question. The part about the number or projectiles fired, etc. is custom logic. You could create variables for this (replicated of course) and use those to drive the damage and number of projectiles (dependent on the Ability Level of course, example a simple multiplication with the Ability Level as a multiplier) . Again, recommend doing this in C++ but it is up to you how you want to do it.

1 Like

Hi! as for the level up ability, I would appreciate if you could provide a code example. also i dont mind cpp!

Sure. Going to bed now, I will try and add it in the evening tomorrow. Good night! :slight_smile:

1 Like

bumping

hey @8Zerocool8, any news?

Hey @GKoch!

Life got in the way, sorry for the delay.

Solution:


Part I: Getting hold of the FGameplayAbilitySpec

  • UAbilitySystemComponent is as you must already know, our gateway to interact with the Gameplay Ability System (GAS). In this class, you will find the following method. UAbilitySystemComponent::FindAbilitySpecFromClass | Unreal Engine Documentation

  • Unless you have an FGameplayAbilitySpecHandle stored somewhere, you will want to use this method to get hold of the FGameplayAbilitySpec for a particular ability (i.e. for a particular ability class).


Part II: Modifying the Ability Level on the Ability Spec

  • Tranek’s GAS Documentation, Leveling up Abilities mentions two ways to level abilities up.
    Option 1: ungranting the ability (remove) and thus removing its FGameplayAbilitySpec from the UAbilitySystemComponent and then granting it again, but now with a higher level
    Option 2: Finding the FGameplayAbilitySpec for the ability for a given actor and then increasing its ability level. We are taking option 2, as it means that the Ability can be leveled up while staying activated simultaneously and is also more performant, as we are not ungranting and granting abilities unnecessarily.
  • So, according to the documentation above, we have to
    → Change the Ability Level on the FGameplayAbilitySpec (on the server!)
    → Mark the FGameplayAbilitySpec as dirty so that the modifications we made, in this case just the ability level change, will get replicated to the client.
//UCustomAbilitySystemComponent.h
//^^ Custom AbilitySystemComponent class, which derives from UAbilitySystemComponent

public:
UFUNCTION(BlueprintAuthorityOnly)
void SetAbilityLevel(TSubclassOf<UGameplayAbility> AbilityClass, int32 NewLevel);



//UCustomAbilitySystemComponent.cpp
void UCustomAbilitySystemComponent::SetAbilityLevel(TSubclassOf<UGameplayAbility> AbilityClass, int32 NewLevel)
{
    //Are we on the server? If not, we should not be modifying Ability Specs!
    if(!HasAuthority())
    { 
        return;
    }

    FGameplayAbilitySpec* AbilitySpec = FindAbilitySpecFromClass(AbilityClass);

    if(Spec)
    {
        Spec->Level = NewLevel;
        MarkAbilitySpecDirty(Spec);
    }
}

Now you could this function, even from blueprints, to modify the AbilityLevel for a particular ability. I have made one assumption, which is very important for this to work, that you are using Instanced per Actor abilities. Check Tranek’s documentation about Instancing policies for more details. The Code snippet provided has not been checked for syntax or tested to work and only provides context as to how you could go about implementing ability level changes.

Hope it helps! :slight_smile:

5 Likes

Thank you so much for your reply! this is just what i was looking for.

1 Like