Gameplay Ability System·Gameplay Abilities·Programming·Unreal Engine

GiveAbilityAndActivateOnce: One-Shot Abilities Without the Cleanup

GiveAbilityAndActivateOnce grants a GAS ability, activates it once, and removes the spec by itself, even for latent abilities. When to use it, the rules, and a full knockdown example.

Most abilities in the Gameplay Ability System ( GAS ) follow the same life: you grant them once when the character spawns, and you activate them many times after that, through input or gameplay events. Your dodge, your attacks, your block. They are standing capabilities.

But some abilities are not capabilities. They are commands. A scripted knockdown. A finisher that plays on the victim. A “do this exact thing right now” order coming from the server. These abilities should run exactly once and then disappear.

I owned the execution system on Lords of the Fallen, and the victim’s side of an execution is exactly this kind of ability: the target receives a “get executed” order, plays it, and should never carry that ability again.

The manual way, and where it goes wrong

You can do one-shot abilities by hand with three calls:

  • GiveAbility to grant it
  • TryActivateAbility to run it
  • ClearAbility to remove it when it ends

And I can tell you what happens with step 3: someone forgets it. Now your ASC is carrying a pile of one-shot specs that will never activate again, and every system that enumerates GetActivatableAbilities() has to filter that clutter forever.

The stock ASC has a function built for exactly this case:

// GameplayAbilities/Public/AbilitySystemComponent.h
FGameplayAbilitySpecHandle GiveAbilityAndActivateOnce(
    FGameplayAbilitySpec& AbilitySpec,
    const FGameplayEventData* GameplayEventData = nullptr);

What it actually does

The name says most of it, but the details matter:

  • It grants the spec.
  • It tries to activate it immediately.
  • It removes the grant afterwards, no matter what.

If the activation fails, the spec is cleared on the spot and you get an invalid handle back, so checking the handle tells you if it ran. If the activation succeeds, the spec is marked to be removed when the ability ends. This is the important part: your one-shot ability can be latent. It can play a montage, wait on ability tasks, take two full seconds — and the grant still cleans itself up the moment EndAbility runs.

Three rules before you use it:

  • Authority only. Granting abilities is always a server operation, and this function refuses to run without authority.
  • Instanced abilities only, and not Local Only. Which is fine, because a one-shot command that plays montages and runs tasks wants to be instanced anyway.
  • Don’t keep the handle around. The spec removes itself, so the handle is only good for reading the immediate result. If unrelated code looks it up later, the spec is already gone.

The rule I follow: any time an ability is conceptually a single command instead of a standing capability, use GiveAbilityAndActivateOnce instead of the three manual calls. You remove the risk of forgetting the cleanup, and your ability list stays clean.

A knockdown bolt, end to end

Here is the pattern in a projectile that knocks down whatever it hits:

void AKnockdownBolt::OnProjectileHit(AActor* HitActor, const FHitResult& Hit)
{
    if (!HasAuthority())
    {
        return;
    }

    UAbilitySystemComponent* TargetASC =
        UAbilitySystemBlueprintLibrary::GetAbilitySystemComponent(HitActor);
    if (!TargetASC)
    {
        return;
    }

    // The event data is your payload: who shot, where it hit, how hard.
    FGameplayEventData EventData;
    EventData.Instigator = GetInstigator();
    EventData.Target = HitActor;
    EventData.EventMagnitude = KnockdownForce;
    EventData.ContextHandle = TargetASC->MakeEffectContext();
    EventData.ContextHandle.AddHitResult(Hit);

    FGameplayAbilitySpec Spec(UGA_GetKnockedDown::StaticClass(), /*Level=*/1, INDEX_NONE, this);
    TargetASC->GiveAbilityAndActivateOnce(Spec, &EventData);
}

That second parameter is the underrated part. The FGameplayEventData travels into the ability as TriggerEventData, so the knockdown can read the impact and react to it:

void UGA_GetKnockedDown::ActivateAbility(const FGameplayAbilitySpecHandle Handle,
    const FGameplayAbilityActorInfo* ActorInfo,
    const FGameplayAbilityActivationInfo ActivationInfo,
    const FGameplayEventData* TriggerEventData)
{
    const FHitResult* Hit = TriggerEventData
        ? TriggerEventData->ContextHandle.GetHitResult()
        : nullptr;

    // Commit, pick the directional knockdown montage from the hit direction,
    // play it with Play Montage and Wait, push the character back,
    // and call EndAbility when the montage finishes.
}

And here is why this beats hardcoding the reaction in the projectile: the ability runs on the target, with the target’s ASC, tags and attributes. A boss with a StatusImmuneKnockdown tag in the ability’s Activation Blocked Tags simply fails the activation — and remember, a failed activation cleans the spec too. The bolt does not need to know any of this. It just fires the command, and GAS answers yes or no.

One networking note so nobody gets surprised: the activation happens on the server. For AI targets, Server Only execution is enough, because the montage plays through the ASC and replicates by default. For player targets you want Server Initiated, so the owning client runs the ability too.

Other places this shines in combat

Once you see the pattern, you find it everywhere:

  • Executions and finishers. The attacker runs their normal finisher ability. The victim receives GiveAbilityAndActivateOnce with the “get executed” ability that plays the synced montage.
  • Traps. A bear trap does not need every character in the game to carry GA_TrappedByBearTrap. It injects it on overlap.
  • Boss phase transitions. The scripted “roar and jump to the center of the arena” runs once, exactly when the AI decides, and never appears in the boss ability list again.
  • Scripted and cutscene moments. Level scripting can make any character perform any ability, without touching how that character was set up.

When NOT to use it

If the behavior should exist for a duration instead of a single moment, this is the wrong tool. “While burning, you have a Panic ability” is not a command, it is a temporary capability — grant it through a Gameplay Effect ( the Grant Abilities component of the effect ) and let the lifetime of the effect add and remove it for you. I covered those components in the Gameplay Effect Components post.

So this is the rule I use:

  • A permanent capability → GiveAbility.
  • A temporary capability tied to an effect → grant it through the Gameplay Effect.
  • A single command → GiveAbilityAndActivateOnce.

Try it this week: search your project for TryActivateAbility. If any of them come right after a GiveAbility, and are followed by a manual ClearAbility — or worse, not followed by one — you have found your first candidate.

Recap

  • GiveAbilityAndActivateOnce grants a spec, activates it, and removes it by itself, even for latent abilities. The cleanup happens when EndAbility runs, and a failed activation cleans up on the spot and returns an invalid handle.
  • It is server-only and needs instanced, non-Local-Only abilities. Don’t store the returned handle; the spec it points to removes itself.
  • The decision is about what the ability is: permanent capability → GiveAbility, temporary capability → Gameplay Effect with Grant Abilities, single command → GiveAbilityAndActivateOnce.

Keep reading

Learning about Ability Instancing Policy in GAS

Learning about Ability Instancing Policy in GAS

So many instancing types!
Making Sense of Gameplay Effect Durations

Making Sense of Gameplay Effect Durations

Instant vs Has Duration vs Infinite
From Wait Delays to Play Montage: 10 useful GAS Ability Tasks

From Wait Delays to Play Montage: 10 useful GAS Ability Tasks

Don't wait a Delay to Play your Montages, use Gameplay Ability Tasks