Casting abilities in Unreal Engine 5 using the Gameplay Ability System
3 min read
While I was working on a game, I had some problems while making the casting system, similar to those found in MOBAs like Dota 2, or MMOs like World of Warcraft.
I created this guide to help others avoid the challenges I faced and achieve great results more efficiently.
The task at hand
This is what the system will achieve:
- Delay ability activation until the casting progress is completed.
- Has to work in multiplayer games.
- Show in the local UI the expected casting time remaining in realtime.
- Be able to reuse the same Gameplay Effect for all the abilities, as to avoid code & asset duplication.
You might find some things missing from the list, like how to handle interruptions. I haven't made the interruption part of the system for my game yet, so I can not provide help with that part. But I think I will handling it with Gameplay Events and that should be compatible with this guide.
Guide
This guide was made for version 5.4 of Unreal Engine. Although it should work for older versions with some tweaks.
The system depends mainly of two things:
- A casting
GameplayEffect. - The
GameplayAbilitythat will handle the castingGameplayEffect.
The Gameplay Effect
The casting GameplayEffect is quite straight forward:
- Set the
Duration PolicytoHas Duration, and the duration to0. - Add a
Grant Tags to Target Actorcomponent that adds aGameplayTagto indicate the casting state (in my case I useCombat.State.Casting). - Optionally, modifiers can be added to the character, like slowing it down while the casting is in progress.
This is how mine looks:

The Gameplay Ability
An instance of the casting GameplayEffect should created with its duration modified before being applied to the owner. This allows the system to reuse the same casting GameplayEffect for all abilities.
Take into account the Duration modification happens on the
GameplayEffectSpecand not onGameplayEffect. Altought this does not matter for this use case, it might matter for more complex setups.
After the casting Gameplay Effect is applied the ability will wait for the casting Gameplay Tag to be removed (Combat.State.Casting in my case). When its removed the casting has finished.
This works in multiplayer games as GameplayTags are replicated and removed on both the server and the client.

I also experimented using OnGameplayEffectRemoved but I had some problems on the clients, as the Gameplay Effect was instantly removed (maybe because what is applied locally is a predicted version that is removed as soon as the server-replicated one is applied...?).
Recommendation
Programming in a Blueprint Macro will allow all our abilities to reuse the same code.
Extra: Modifying casting duration from attributes
For my game I need to be able to modify the casting time based on an Attribute. For this I have created the following C++ code that is available for all my Gameplay Abilities.
It recalculates from a BaseCastingTime (the default time the ability should take to cast) the real time based on an attribute called CastingSpeed that allows Gameplay Effects like buffs and debuffs to change the final casting time.
FGameplayEffectSpecHandle UBaseGameplayAbility::GenerateCastingGameplayEffectSpec(
const FGameplayEffectSpecHandle& GameplayEffectSpecHandle,
const float BaseCastingTime
) {
const FGameplayEffectSpec Spec = *GameplayEffectSpecHandle.Data.Get();
const FGameplayTagContainer* SourceTags = Spec.CapturedSourceTags.GetAggregatedTags();
const FGameplayTagContainer* TargetTags = Spec.CapturedTargetTags.GetAggregatedTags();
FAggregatorEvaluateParameters EvaluationParameters;
EvaluationParameters.SourceTags = SourceTags;
EvaluationParameters.TargetTags = TargetTags;
// Calculate the new CastingTime from the modifiers (buffs/debuffs)
// of the CastingSpeed attribute
bool bSuccess;
const float TotalCastingTime = UAbilitySystemBlueprintLibrary::EvaluateAttributeValueWithTagsAndBase(
Spec.GetContext().GetInstigatorAbilitySystemComponent(),
UFocusAttributeSet::GetCastingSpeedAttribute(),
*Spec.CapturedSourceTags.GetAggregatedTags(),
*Spec.CapturedTargetTags.GetAggregatedTags(),
BaseCastingTime, // Use the BaseCastingTime to calculate the value from
bSuccess
);
// Set the duration of the Gameplay Effect Spec
GameplayEffectSpecHandle.Data->SetDuration(TotalCastingTime, true);
return GameplayEffectSpecHandle;
}
This code can replace the SetDuration method in blueprints.

Conclusion
Unreal's Gameplay Ability System provides a phenomenal framework for developers to extend with their game specific mechanics.
The casting system explored in this guide is independent, expandable, composable and can be used in all the Gameplay Abilities the developer wants.
Always keep in mind that there might be better ways to create a casting system for your specific game mechanics, keep exploring your game needs.
I hope you have learned something new!
Made by Lorwen with 🧡