Checking if Gameplay Ability is Active.
Updated for UE 5.8:
UGameplayAbility::AbilityTagsis deprecated in favor ofGetAssetTags(), and the class/source lookup is now written out explicitly.
The stock ASC does not give you a simple “is this ability running right now?” query, but the data is all there: a FGameplayAbilitySpec is active whenever its ActiveCount is above zero, and FGameplayAbilitySpec::IsActive() tells you that. Here are three overloads I add to my custom Ability System Component, one for each way you are likely to identify an ability: by tags, by spec handle, or by class.
bool UKaosAbilitySystemComponent::IsAbilityActive(const FGameplayTagContainer* WithTags, const FGameplayTagContainer* WithoutTags, UGameplayAbility* Ignore)
{
ABILITYLIST_SCOPE_LOCK();
for (const FGameplayAbilitySpec& Spec : GetActivatableAbilities())
{
if (!Spec.IsActive() || Spec.Ability == nullptr || Spec.Ability == Ignore)
{
continue;
}
const FGameplayTagContainer& AbilityTags = Spec.Ability->GetAssetTags();
const bool bWithTagPass = (!WithTags || AbilityTags.HasAny(*WithTags));
const bool bWithoutTagPass = (!WithoutTags || !AbilityTags.HasAny(*WithoutTags));
if (bWithTagPass && bWithoutTagPass)
{
return true;
}
}
return false;
}
bool UKaosAbilitySystemComponent::IsAbilityActive(const FGameplayAbilitySpecHandle& InHandle) const
{
const FGameplayAbilitySpec* Spec = FindAbilitySpecFromHandle(InHandle);
return Spec && Spec->IsActive();
}
bool UKaosAbilitySystemComponent::IsAbilityActive(TSubclassOf<UGameplayAbility> AbilityClass, UObject* SourceObject)
{
ABILITYLIST_SCOPE_LOCK();
for (const FGameplayAbilitySpec& Spec : GetActivatableAbilities())
{
if (Spec.Ability && Spec.Ability->GetClass() == AbilityClass && (!SourceObject || Spec.SourceObject == SourceObject))
{
return Spec.IsActive();
}
}
return false;
}
Notes and gotchas:
ABILITYLIST_SCOPE_LOCK()(which needs a non-const ASC, so these two are not const) stops the ability list being modified (abilities cleared or removed) while you iterate it. It is not needed for the handle overload, as that is a single lookup.- The class overload matches the exact class (like
FindAbilitySpecFromClass), not subclasses. It returns on the first spec that matches, so if you grant the same class several times with different source objects, pass theSourceObject. - The tag overload only looks at the ability’s asset tags (what used to be
AbilityTags). Tags granted per spec throughGetDynamicSpecSourceTags()are not checked here. - If all you need is “is something like this running”, giving the ability
ActivationOwnedTagsand checking for that tag on the ASC is often simpler and cheaper than looping the specs.