GameplayAbilities and you

I would be curious too, actually. There’s a compelling point to be made that tying a cast time/channel/whatever to a visual animation is probably very stupid for the simple reason that tying functionality to visuals and not the toher way around tends to be a no-no, but on the other hand you could just make it so that the montage playback rate is adjusted so that the montage duration adjusts itself to a concretely defined duration variable in the ability(basically make the play rate of the montage (normal montage duration / Cast time value) ), and not the other way around. Then you’d ultimately be left with just a delay node that ensures that the animation tied to the ability must be played until the end, which can be crucial for games where visual tells are key.

It would also seem strange to me that you’d have to split a montage for a before-effect and after-effect section of an animation. Would you do a delay task that would perhaps be ended prematurely if the animation itself is cancelled/interrupted, would you actually have to split and play 2 montage tasks, would you create a new ability task class that is set up to listen for, say, an animation notify within the montage passed as parameter, or what?

I wonder if it would be too much to ask for an example ability implementation from a random active Paragon ability of choice. Prob’ly, but it could answer some questions about what the practices for each thing are.

Well honestly I do not see the benefit of that philosophy. I use animations to sync stuff up without needing to enter arbitrary magic numbers for ranges.

As an example - I use a modified version of the state machine plugin that was developed on the fighting game training livestream. They entered ranges for cancel windows which was a big no for me as our animations are often being tweaked, sped up, slowed down etc. by the gameplay designers. What I ended up doing is create an anim notify that simply allows the curent move to cancel. As such I define my cancel windows via notifies. This is especially important since we have named cancel windows (cancel for next melee swing, cancel for special attack etc.)

The cast time argument isn’t really valid because for those situations you usually have CastStart, CastLoop and CastExecute. You simply stick to the loop as long as your cast time is.

In an ideal world animations would only be the presentation layer but the way I see it this is an example of rigid design philosophy actually standing in the way of the design.

I don’t think either answer is truly right in all situations, because games with an almost fighting game-esque focus on animations and visual cues pretty much require an animation and the frame- and hitbox-data of that animation to be very closely intertwined, because in a way the animation is pretty much the attack in such a case. At the same time, MOBAs such as Dota are primarily number games, and the timing of the effect itself is what’s important, not the animation of the comparably tiny character that mostly only aids in making what skills are used easier to follow. As such, changing the animation itself should have no business changing the actual casting time.

Yes but that is a moot point. Any spell with a cast time will have a 3 phase montage - start, loop and end.You will simply keep the montage in the loop state until the cast time is done.

Hi, I want to add another thanks to KSJ for creating this.

I’ve been playing with and making small modifications to the sample project and feeling pretty good about things. One thing I’m unsure of is the proper way to display information to the user (via widget for example)

Things I would like to show but haven’t figured out how:

  • a list of all effects currently active on the player (e.g. buff/debuff icons)
  • time remaining of temporary effects
  • time remaining for ability cooldown effects

Things I did figure out how:

  • Health or any other attribute (by using the get attribute node shown below)

For a list of all current effects you can query the tags on that player. If you’re finding you need to do this a lot then I think you should step back for a minute and think about whether you can do it in a more modular way. I have a lot of status effects in a fairly standard dungeon crawler and the only time I iterate over all the tags/effects is when I’m debugging.

For time remaining of effects you can use one of several methods like:

[FONT=Courier New]
TArray<float> GetActiveEffectsTimeRemaining(const FGameplayEffectQuery& Query) const;

but this method isn’t exposed to blueprint and for HUD icons of status effects (like slow or burning or whatever) you might be want to put it in the cue.

since cooldowns are effects, you can use the same system to get time remaining for cooldowns. There is a convenience method
[FONT=Courier New]
UFUNCTION(BlueprintCallable, Category = Ability)
float GetCooldownTimeRemaining() const;

Hey guys, just a quick heads up - I started my own analysis on this system and so far I’ve written a comprehensive analysis on Ability Sets. You can take a look here.

Hello,

thanks for this very useful post.

I have started to investigate the system a bit, and I’m now in the process of converting some of the abilities I coded by hand in C++ to this system.

I have a pretty good understanding of the various elements of the system, but I don’t get why I have this issue with my attempt to implement a Sprint ability.

So far, I have this game play ability:

As you can see, once my ability starts, I apply a GameplayEffect GE_Sprint_Stamina and wait to end the ability for the player to release the sprint button, or when he runs out of stamina.

Once the ability ends, I remove all game play effects which granted the Abilities.Movement.Sprint tag to the owner.

Here is my gameplay effect:

It is pretty simple I think : I just periodically decrease the stamina, and I grant the Abilities.Movement.Sprint.

This works well. When I press the sprint button, the stamina starts to decrease, until I release the button.

So far, so good.

But…

In the tick event of the blueprint of the character, I iterate over all the tags, to check the tag has been correctly removed:

Once I start sprinting, I can see the tag is in the list. But when I release the button, the tag is still displayed each tick.

Is there a better solution to this?

Thanks and keep the good work ! :slight_smile:

After digging in the source code, I confirm the tags are correctly removed from the ability system component when the ability ends.

The problem lies in the output of the owned tags I display each tick.

I also tried with the built-in GetDebugStringFromGameplayTagContainer, but with the same outcome.

Hello,

I have another question: how would you go to undo a modifier when a game play effect ends?

I have 2 attributes : WalkSpeed and WalkSpeedMultiplier. I also have a Sprint ability. When this ability is active, I would like to set multiply the WalkspeedModifier by 2.0f for example. And when the sprint ability is ended, I would like to divide this WalkSpeedMultiplier by 2.0f.

Thinking about this, my assumption is that it is only possible using 2 gameplay effects.

Am I correct?

Maybe I misunderstand the question, but don’t you just need to have one permanent gameplay effect for this? Modifiers come and go with the GameplayEffect they’re attached to, unless their Gameplay Effect is instant, in which case they become permanent.

No you got the question right.

I got confused because of this weird issue I was talking about before. The debug output of all the game play tags was displaying all the tags the owner ever had, including those who were not supposed to be active.

Your answer is correct too. I had to set the duration of the effects to Infinite to undo the buff when the gameplay effect is remoed :slight_smile:

Hi guys, I’m wasting days trying to understand this Gameplay Abilities system but some things are still unclear to me.
My problem is not using C++, I use it regularly, my problem is how to design spells using this system, there are only simple examples on the Web.

Let’s say I want to make a spell like this one:

1.Casts for 1 second
2.Every 3 seconds heals the player
3.When the duration ends it enables another spell

To heal periodically I can simply use a GameplayEffect with a period of X seconds, my real problem is that I can’t find a way to activate an ability when a GameplayEffect ends (there is only OwnedTagAdded but not OwnedTagRemoved) and how to create a Casting time.

How would you create the spell mentioned above using the Gameplay Abilities?

To activate an ability from a gameplay effect, I think you can use the triggers of that ability, which can watch whenever a tag is added to the owner.

For the 1 second cast time, in your ability, I would add a WaitDelay task of 1 second right after your ability starts, from which you would plug your gameplay code. I would also add a WaitInputRelease task to cancel if the player released the button before that 1 second delay for example, if you need.

I think that would be a good starting point (I don’t have a lot of experience with the system right now)

Could you expand a bit on this? How would you go about making a HUD with cooldowns? Or tie things to the HUD in general. Is it possible with blueprints?

If you’re asking for pure blueprint solutions then GameplayAbilities is unlikely to fit the bill. You can query the cooldown time remaining based on which cooldown effect you’ve assigned to an ability, how you tie that to your HUD is entirely up to you. You could put a translucent tint progressbar on top of each ability icon and bind its %age based on the cooldown time for something quite cheap, or display a rounded integer, or whatever. I don’t use cooldowns at the moment since my abilities are all mana cost, so I don’t have an example to show sorry.

Okay, thanks.

Could anyone tell me some of the limitations of the system? What situations would it not be suitable in? Would using it in a high-speed FPS with 20+ players be wise? What is its networking performance compared to doing abilities more directly. Thanks for any insight. It seems powerful, but I’m not sure if I should invest the time it takes to learn it.

The problem with answering this is it requires someone to have built a fairly mechanically complete and performance sensitive multiplayer game to really answer it. I’m a small part of the way there, with a couple dozen abilities and a couple dozen status effects - I can only share my experience. Network performance is proving to be problematic with 20 bots randomly firing skills at each other on a dedicated server, but it’s very difficult to tell if that’s mistakes and inexperience on my part or limitations of the system. I see a lot of dropped packets resulting in abilities not firing, and in the logs I can see “LogNetPlayerMovement:Warning: CreateSavedMove: Hit limit of 96 saved moves (timing out or very bad ping?)” coming up from time to time.

My hunch is this is due to issues in my code or how I’ve structured effects/cues, since when I think of Paragon there are creep waves + 10 players, so there’s in theory quite a lot of AbilityComponent avatars on the field.

I configured a GameplayAbility with a GameplayEffect as cooldown. It’s working well but now I want to get the cooldown time to show on the UI.
I am trying to use the function GetCooldownTimeRemaining() but it always returns 0. To get the UGameplayAbility I use this:


	FGameplayAbilitySpec* AbilitySpec = AbilitySystem->FindAbilitySpecFromClass(Ability);

	if (AbilitySpec && AbilitySpec->Ability)
	{
		float TimeRemaining = AbilitySpec->Ability->GetCooldownTimeRemaining();
		UE_LOG(LogTemp, Warning, TEXT("Time Remaining %f"), TimeRemaining);
	}


I assume that this is incorrect. How I obtain the GameplayAbility correctly to get the cooldown?