Skip to main content

Updated May 4, 2026

Gameplay cues

Why this matters​

Gameplay Cues are how GAS keeps "what happened, mechanically" separate from "what it looks and sounds like." Without them, the natural place to spawn a hit-flash particle or play a cast sound is inside the ability or effect that caused it — which means every gameplay author also has to touch VFX code, and every VFX tweak risks touching gameplay logic. A Gameplay Cue is triggered by a tag, not called directly, so an artist can rework impact effects entirely without a gameplay programmer in the loop, and the same cue can be triggered from C++, Blueprint, or a Gameplay Effect asset without caring which one did it.

Mental model​

The trigger never references a specific class — it only names a tag under the GameplayCue. root. The Gameplay Cue Manager owns the mapping from tag to handler, so adding, removing, or reskinning a cue's implementation is a data change, not a code change.

Notify types: Static vs Actor​

  • UGameplayCueNotify_Static — a stateless handler with no spawned actor; its OnExecute runs a burst of logic (spawn a Niagara system, play a sound) and returns. Use this for one-shot cosmetics that don't need to persist or track state — most impact effects.
  • AGameplayCueNotify_Actor — a real, spawned actor that can persist for the cue's WhileActive duration, useful for a looping effect (a burning aura, a channeling beam) that needs to track and clean up an ongoing visual over time. Costs more than Static — only reach for it when the cue genuinely needs actor lifetime.

Execute vs Add/Remove​

Gameplay Cues distinguish momentary and durational events:

  • Execute — fire-and-forget, for an instant event (a hit landing, a cast completing). Calls the handler's execute path once; nothing persists afterward.
  • Add / Remove (paired with WhileActive) — for a cue tied to a durational or infinite Gameplay Effect: Add fires when the effect is applied, WhileActive covers the period the effect remains active (used by AGameplayCueNotify_Actor to drive a looping visual), and Remove fires when the effect ends.
Executing a one-shot cue from an ability
FGameplayCueParameters CueParams;
CueParams.Location = GetAvatarActorFromActorInfo()->GetActorLocation();
CueParams.Instigator = GetAvatarActorFromActorInfo();

AbilitySystemComponent->ExecuteGameplayCue(
MyGameplayTags::GameplayCue_Fireball_Impact, CueParams);
A GameplayEffect that adds a cue for its duration
UGE_BurningDebuff::UGE_BurningDebuff()
{
DurationPolicy = EGameplayEffectDurationType::HasDuration;
GameplayCues.Add(MyGameplayTags::GameplayCue_Burning); // Add on apply, Remove on expiry
}
MyGameplayCue_FireballImpact.h — a Static notify
UCLASS()
class MYGAME_API UMyGameplayCue_FireballImpact : public UGameplayCueNotify_Static
{
GENERATED_BODY()

public:
virtual bool OnExecute_Implementation(AActor* Target, const FGameplayCueParameters& Parameters) const override;

protected:
UPROPERTY(EditDefaultsOnly, Category = "Cue")
TObjectPtr<UNiagaraSystem> ImpactEffect;

UPROPERTY(EditDefaultsOnly, Category = "Cue")
TObjectPtr<USoundBase> ImpactSound;
};

The cosmetic-only rule​

Gameplay Cues must never change gameplay state — no attribute writes, no ability grants, no tag changes that anything else depends on. Their entire contract is "make the already-decided gameplay outcome visible and audible." The reason is replication: Gameplay Cues are, by design, allowed to be locally predicted and locally suppressed (e.g., not relevant to a distant client), so any gameplay effect hiding inside one will run inconsistently between server and clients, or not at all for players who can't see the cue.

Gotchas​

Do not put gameplay logic in a GameplayCueNotify

If a design need seems to require it ("the cue also needs to apply a slow effect"), that's a sign the slow effect belongs in the Gameplay Effect or ability that triggered the cue, not in the cue itself. Keep the cue's OnExecute/OnActive/OnRemove strictly presentational.

Static vs Actor is a real cost decision, not a style choice

Defaulting every cue to GameplayCueNotify_Actor "just in case it needs to persist later" spawns and replicates an actor for effects that don't need one. Start with GameplayCueNotify_Static and only promote to Actor when a cue genuinely needs to track state across WhileActive.

Cue tags follow the same hierarchy discipline as any other gameplay tag

A GameplayCue. tag with no matching registered notify silently does nothing — there's no compile-time link between the tag used to trigger a cue and the notify asset registered to handle it. Verify new cue tags actually resolve to a handler in the Gameplay Cue Manager, especially after a tag rename.

See also​